From 17e8e013ff321e55af0622e5818926969a25c26a Mon Sep 17 00:00:00 2001
From: Violette Roche-Montane <violette.roche-montane@forgerock.com>
Date: Fri, 04 Apr 2014 09:46:13 +0000
Subject: [PATCH] Checkpoint for OPENDJ-1303 "opendj-cli" Preparing the ground to code cleanup the LDAPConnectionConsoleInteraction. - Added messages from utility.properties / quicksetup.properties. - Added functions to Utils. - Minor mods on the ConnectionFactoryProvider : accessors, added getters and extracted checkForConflictingArguments().

---
 opendj-cli/src/main/java/com/forgerock/opendj/cli/Utils.java                     |   53 ++++++++++
 opendj-cli/src/main/java/com/forgerock/opendj/cli/ConnectionFactoryProvider.java |  163 +++++++++++++++++++-------------
 opendj-cli/src/main/resources/com/forgerock/opendj/cli/cli.properties            |   63 ++++++++++++
 3 files changed, 211 insertions(+), 68 deletions(-)

diff --git a/opendj-cli/src/main/java/com/forgerock/opendj/cli/ConnectionFactoryProvider.java b/opendj-cli/src/main/java/com/forgerock/opendj/cli/ConnectionFactoryProvider.java
index 0709410..f1ac91e 100644
--- a/opendj-cli/src/main/java/com/forgerock/opendj/cli/ConnectionFactoryProvider.java
+++ b/opendj-cli/src/main/java/com/forgerock/opendj/cli/ConnectionFactoryProvider.java
@@ -339,6 +339,24 @@
     }
 
     /**
+     * Indicate if the SSL mode is required.
+     *
+     * @return True if SSL mode is required
+     */
+    public boolean useSSL() {
+        return useSSLArg.isPresent();
+    }
+
+    /**
+     * Indicate if the startTLS mode is required.
+     *
+     * @return True if startTLS mode is required
+     */
+    public boolean useStartTLS() {
+        return useStartTLSArg.isPresent();
+    }
+
+    /**
      * Checks if any conflicting arguments are present, build the connection with
      * selected arguments and returns the connection factory.
      *
@@ -351,71 +369,7 @@
         if (connFactory == null) {
             port = portArg.getIntValue();
 
-            // Couldn't have at the same time bindPassword and bindPasswordFile
-            if (bindPasswordArg.isPresent() && bindPasswordFileArg.isPresent()) {
-                final LocalizableMessage message =
-                        ERR_TOOL_CONFLICTING_ARGS.get(bindPasswordArg.getLongIdentifier(),
-                                bindPasswordFileArg.getLongIdentifier());
-                throw new ArgumentException(message);
-            }
-
-            /*
-             * Couldn't have at the same time trustAll and trustStore related arg
-             */
-            if (trustAllArg.isPresent() && trustStorePathArg.isPresent()) {
-                final LocalizableMessage message =
-                        ERR_TOOL_CONFLICTING_ARGS.get(trustAllArg.getLongIdentifier(),
-                                trustStorePathArg.getLongIdentifier());
-                throw new ArgumentException(message);
-            }
-            if (trustAllArg.isPresent() && trustStorePasswordArg.isPresent()) {
-                final LocalizableMessage message =
-                        ERR_TOOL_CONFLICTING_ARGS.get(trustAllArg.getLongIdentifier(),
-                                trustStorePasswordArg.getLongIdentifier());
-                throw new ArgumentException(message);
-            }
-            if (trustAllArg.isPresent() && trustStorePasswordFileArg.isPresent()) {
-                final LocalizableMessage message =
-                        ERR_TOOL_CONFLICTING_ARGS.get(trustAllArg.getLongIdentifier(),
-                                trustStorePasswordFileArg.getLongIdentifier());
-                throw new ArgumentException(message);
-            }
-
-            /*
-             * Couldn't have at the same time trustStorePasswordArg and trustStorePasswordFileArg
-             */
-            if (trustStorePasswordArg.isPresent() && trustStorePasswordFileArg.isPresent()) {
-                final LocalizableMessage message =
-                        ERR_TOOL_CONFLICTING_ARGS.get(trustStorePasswordArg.getLongIdentifier(),
-                                trustStorePasswordFileArg.getLongIdentifier());
-                throw new ArgumentException(message);
-            }
-
-            if (trustStorePathArg.isPresent()) {
-                // Check that the path exists and is readable
-                final String value = trustStorePathArg.getValue();
-                if (!canReadPath(value)) {
-                    final LocalizableMessage message = ERR_CANNOT_READ_TRUSTSTORE.get(value);
-                    throw new ArgumentException(message);
-                }
-            }
-
-            if (keyStorePathArg.isPresent()) {
-                // Check that the path exists and is readable
-                final String value = keyStorePathArg.getValue();
-                if (!canReadPath(value)) {
-                    final LocalizableMessage message = ERR_CANNOT_READ_KEYSTORE.get(value);
-                    throw new ArgumentException(message);
-                }
-            }
-
-            // Couldn't have at the same time startTLSArg and useSSLArg
-            if (useStartTLSArg.isPresent() && useSSLArg.isPresent()) {
-                final LocalizableMessage message =
-                        ERR_TOOL_CONFLICTING_ARGS.get(useStartTLSArg.getLongIdentifier(), useSSLArg
-                                .getLongIdentifier());
-                throw new ArgumentException(message);
-            }
+            checkForConflictingArguments();
 
             try {
                 if (useSSLArg.isPresent() || useStartTLSArg.isPresent()) {
@@ -455,6 +409,81 @@
     }
 
     /**
+     * Verifies if the arguments are not conflicting together or if they are readable.
+     *
+     * @throws ArgumentException
+     *             If arguments are conflicting or if the files cannot be read,
+     *             an argument exception is thrown.
+     */
+    private void checkForConflictingArguments() throws ArgumentException {
+        // Couldn't have at the same time bindPassword and bindPasswordFile
+        if (bindPasswordArg.isPresent() && bindPasswordFileArg.isPresent()) {
+            final LocalizableMessage message =
+                    ERR_TOOL_CONFLICTING_ARGS.get(bindPasswordArg.getLongIdentifier(),
+                            bindPasswordFileArg.getLongIdentifier());
+            throw new ArgumentException(message);
+        }
+
+        /*
+         * Couldn't have at the same time trustAll and trustStore related arg
+         */
+        if (trustAllArg.isPresent() && trustStorePathArg.isPresent()) {
+            final LocalizableMessage message =
+                    ERR_TOOL_CONFLICTING_ARGS.get(trustAllArg.getLongIdentifier(),
+                            trustStorePathArg.getLongIdentifier());
+            throw new ArgumentException(message);
+        }
+        if (trustAllArg.isPresent() && trustStorePasswordArg.isPresent()) {
+            final LocalizableMessage message =
+                    ERR_TOOL_CONFLICTING_ARGS.get(trustAllArg.getLongIdentifier(),
+                            trustStorePasswordArg.getLongIdentifier());
+            throw new ArgumentException(message);
+        }
+        if (trustAllArg.isPresent() && trustStorePasswordFileArg.isPresent()) {
+            final LocalizableMessage message =
+                    ERR_TOOL_CONFLICTING_ARGS.get(trustAllArg.getLongIdentifier(),
+                            trustStorePasswordFileArg.getLongIdentifier());
+            throw new ArgumentException(message);
+        }
+
+        /*
+         * Couldn't have at the same time trustStorePasswordArg and trustStorePasswordFileArg
+         */
+        if (trustStorePasswordArg.isPresent() && trustStorePasswordFileArg.isPresent()) {
+            final LocalizableMessage message =
+                    ERR_TOOL_CONFLICTING_ARGS.get(trustStorePasswordArg.getLongIdentifier(),
+                            trustStorePasswordFileArg.getLongIdentifier());
+            throw new ArgumentException(message);
+        }
+
+        if (trustStorePathArg.isPresent()) {
+            // Check that the path exists and is readable
+            final String value = trustStorePathArg.getValue();
+            if (!canReadPath(value)) {
+                final LocalizableMessage message = ERR_CANNOT_READ_TRUSTSTORE.get(value);
+                throw new ArgumentException(message);
+            }
+        }
+
+        if (keyStorePathArg.isPresent()) {
+            // Check that the path exists and is readable
+            final String value = keyStorePathArg.getValue();
+            if (!canReadPath(value)) {
+                final LocalizableMessage message = ERR_CANNOT_READ_KEYSTORE.get(value);
+                throw new ArgumentException(message);
+            }
+        }
+
+        // Couldn't have at the same time startTLSArg and useSSLArg
+        if (useStartTLSArg.isPresent() && useSSLArg.isPresent()) {
+            final LocalizableMessage message =
+                    ERR_TOOL_CONFLICTING_ARGS.get(useStartTLSArg.getLongIdentifier(), useSSLArg
+                            .getLongIdentifier());
+            throw new ArgumentException(message);
+        }
+    }
+
+    /**
      * Returns the authenticated connection factory.
      *
      * @return The authenticated connection factory.
@@ -739,10 +768,12 @@
      *
      * @return A set of <CODE>TrustManager</CODE> objects that may be used for
      *         interactions requiring access to a trust manager.
+     * @throws IOException
+     *             If the trust store file could not be found or could not be read.
      * @throws GeneralSecurityException
      *             If a problem occurs while interacting with the trust store.
      */
-    private TrustManager getTrustManager() throws IOException, GeneralSecurityException {
+    public TrustManager getTrustManager() throws IOException, GeneralSecurityException {
         if (trustAllArg.isPresent()) {
             return TrustManagers.trustAll();
         }
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 d93be76..47f5413 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
@@ -51,6 +51,8 @@
 import javax.net.ssl.SSLHandshakeException;
 
 import org.forgerock.i18n.LocalizableMessage;
+import org.forgerock.i18n.LocalizableMessageBuilder;
+import org.forgerock.i18n.LocalizableMessageDescriptor;
 import org.forgerock.opendj.ldap.DN;
 import org.forgerock.opendj.ldap.RDN;
 
@@ -492,6 +494,30 @@
     }
 
     /**
+     * Returns a localized message for a given properties key an throwable.
+     *
+     * @param message
+     *            prefix
+     * @param t
+     *            the throwable for which we want to get a message.
+     * @return a localized message for a given properties key and throwable.
+     */
+    public static LocalizableMessage getThrowableMsg(final LocalizableMessage message, final Throwable t) {
+        final LocalizableMessageBuilder mb = new LocalizableMessageBuilder(message);
+        LocalizableMessageDescriptor.Arg1<Object> tag;
+        if (isOutOfMemory(t)) {
+            tag = INFO_EXCEPTION_OUT_OF_MEMORY_DETAILS;
+        } else {
+            tag = INFO_EXCEPTION_DETAILS;
+        }
+        String detail = t.toString();
+        if (detail != null) {
+            mb.append("  ").append(tag.get(detail));
+        }
+        return mb.toMessage();
+    }
+
+    /**
      * Returns <CODE>true</CODE> if we can write on the provided path and <CODE>false</CODE> otherwise.
      *
      * @param path
@@ -517,7 +543,7 @@
      * Returns {@code true} if the the provided string is a DN and {@code false} otherwise.
      *
      * @param dn
-     *            the String we are analyzing.
+     *            The String we are analyzing.
      * @return {@code true} if the the provided string is a DN and {@code false} otherwise.
      */
     public static boolean isDN(String dn) {
@@ -536,7 +562,30 @@
      *            The UID to be used to generate the DN.
      * @return The DN of the administrator for the given UID.
      */
-    private static String getAdministratorDN(String uid) {
+    public static String getAdministratorDN(String uid) {
         return "cn=" + RDN.valueOf(uid) + ",cn=Administrators, cn=admin data";
     }
+
+    /**
+     * Tells whether this throwable has been generated for an out of memory error or not.
+     *
+     * @param t
+     *            The throwable to analyze.
+     * @return {@code true} if the throwable was generated by an out of memory error and false otherwise.
+     */
+    private static boolean isOutOfMemory(Throwable t) {
+        boolean isOutOfMemory = false;
+        while (!isOutOfMemory && (t != null)) {
+            if (t instanceof OutOfMemoryError) {
+                isOutOfMemory = true;
+            } else if (t instanceof IOException) {
+                final String msg = t.toString();
+                if (msg != null) {
+                    isOutOfMemory = msg.contains("Not enough space");
+                }
+            }
+            t = t.getCause();
+        }
+        return isOutOfMemory;
+    }
 }
diff --git a/opendj-cli/src/main/resources/com/forgerock/opendj/cli/cli.properties b/opendj-cli/src/main/resources/com/forgerock/opendj/cli/cli.properties
index e1760b8..c54e16c 100755
--- a/opendj-cli/src/main/resources/com/forgerock/opendj/cli/cli.properties
+++ b/opendj-cli/src/main/resources/com/forgerock/opendj/cli/cli.properties
@@ -461,6 +461,7 @@
 INFO_CATEGORY_PLACEHOLDER={category}
 INFO_PSEARCH_PLACEHOLDER=ps[:changetype[:changesonly[:entrychgcontrols]]]
 INFO_ADMINUID_PLACEHOLDER={adminUID}
+INFO_NOT_AVAILABLE_LABEL=<not available>
 ERR_CANNOT_READ_TRUSTSTORE=Cannot access trust store '%s'.  Verify \
  that the provided trust store exists and that you have read access rights to it
 ERR_CANNOT_READ_KEYSTORE=Cannot access key store '%s'.  Verify \
@@ -887,4 +888,66 @@
 ERR_FAILED_TO_CONNECT_NOT_TRUSTED=Unable to connect to the \
  server at %s on port %s. In non-interactive mode, if the trustStore related parameters are not used, \
  you must use the '--trustAll' option for remote connections
+INFO_EXCEPTION_OUT_OF_MEMORY_DETAILS=Not enough memory to perform the \
+ operation.  Details: %s
+INFO_EXCEPTION_DETAILS=Details: %s
+INFO_LDAP_CONN_PROMPT_SECURITY_LDAP=LDAP
+INFO_LDAP_CONN_PROMPT_SECURITY_USE_SSL=LDAP with SSL
+INFO_LDAP_CONN_PROMPT_SECURITY_USE_START_TLS=LDAP with StartTLS
+INFO_LDAP_CONN_PROMPT_SECURITY_USE_TRUST_ALL=Automatically \
+  trust
+INFO_LDAP_CONN_PROMPT_SECURITY_TRUSTSTORE_PATH=Truststore path:
+INFO_LDAP_CONN_PROMPT_SECURITY_TRUSTSTORE_PASSWORD=Password for \
+  truststore '%s':
+INFO_LDAP_CONN_PROMPT_SECURITY_KEYSTORE_PATH=Keystore path:
+INFO_LDAP_CONN_PROMPT_SECURITY_KEYSTORE_PASSWORD=Password for keystore \
+  '%s':
+INFO_LDAP_CONN_HEADING_CONNECTION_PARAMETERS=>>>> Specify OpenDJ LDAP \
+  connection parameters
+ERR_LDAP_CONN_BAD_HOST_NAME=The hostname "%s" could not be \
+  resolved. Please check you have provided the correct address
+ERR_LDAP_CONN_BAD_PORT_NUMBER=Invalid port number "%s". Please \
+  enter a valid port number between 1 and 65535
+INFO_LDAP_CONN_PROMPT_HOST_NAME=Directory server hostname or IP address \
+  [%s]:
+INFO_LDAP_CONN_PROMPT_SECURITY_USE_SECURE_CTX=How do you want to connect?
+INFO_LDAP_CONN_PROMPT_SECURITY_PROTOCOL_DEFAULT_CHOICE=%d
+ERR_LDAP_CONN_PROMPT_SECURITY_INVALID_FILE_PATH=The provided path \
+  is not valid
+INFO_LDAP_CONN_PROMPT_SECURITY_TRUST_METHOD=How do you want to trust the server certificate?
+INFO_LDAP_CONN_PROMPT_SECURITY_TRUSTSTORE=Use a truststore
+INFO_LDAP_CONN_PROMPT_SECURITY_MANUAL_CHECK=Manually validate
+INFO_LDAP_CONN_PROMPT_SECURITY_SERVER_CERTIFICATE=Server Certificate:
+INFO_LDAP_CONN_SECURITY_SERVER_CERTIFICATE=%s
+INFO_LDAP_CONN_PROMPT_SECURITY_TRUST_OPTION=Do you trust this server certificate?
+INFO_LDAP_CONN_PROMPT_SECURITY_TRUST_OPTION_NO=No
+INFO_LDAP_CONN_PROMPT_SECURITY_TRUST_OPTION_SESSION=Yes, for this session only
+INFO_LDAP_CONN_PROMPT_SECURITY_TRUST_OPTION_ALWAYS=Yes, also add it to a truststore
+INFO_LDAP_CONN_PROMPT_SECURITY_CERTIFICATE_DETAILS=View certificate details
+INFO_LDAP_CONN_SECURITY_SERVER_CERTIFICATE_USER_DN=User DN  : %s
+INFO_LDAP_CONN_SECURITY_SERVER_CERTIFICATE_VALIDITY=Validity : From '%s'%n             To '%s'
+INFO_LDAP_CONN_SECURITY_SERVER_CERTIFICATE_ISSUER=Issuer   : %s
+INFO_LDAP_CONN_PROMPT_SECURITY_CERTIFICATE_ALIASES=Which certificate do you want to use?
+INFO_LDAP_CONN_PROMPT_SECURITY_CERTIFICATE_ALIAS=%s (%s)
+INFO_LDAP_CONN_PROMPT_ADMINISTRATOR_UID=Global Administrator User ID [%s]:
+INFO_LDAP_CONN_GLOBAL_ADMINISTRATOR_OR_BINDDN_PROMPT=Global Administrator \
+ User ID, or bind DN if no Global Administrator is defined [%s]:
+INFO_LDAP_CONN_PROMPT_PORT_NUMBER=Directory server port number [%d]:
+INFO_LDAP_CONN_PROMPT_BIND_DN=Administrator user bind DN [%s]:
+INFO_ADMIN_CONN_PROMPT_PORT_NUMBER=Directory server administration port number [%d]:
+INFO_ERROR_CONNECTING_TO_LOCAL=An error occurred connecting to the server
+INFO_CERTIFICATE_NOT_TRUSTED_TEXT_CLI=The Certificate presented by the server \
+ %s:%s could not be trusted.\nPossible reasons for this error:\n\
+ -The Certificate Authority that issued the certificate is not recognized (this \
+ is the case of the self-signed certificates).\n-The server's certificate is \
+ incomplete due to a misconfiguration.\n-The server's certificate has \
+ expired.\n-There is a time difference between the server machine clock and \
+ the local machine clock.\nBefore accepting this certificate, you should \
+ examine the server's certificate carefully.
+INFO_CERTIFICATE_NAME_MISMATCH_TEXT_CLI=The Certificate presented by the server \
+ %s:%s could not be trusted.\nThere is a name mismatch between the name of \
+ the server (%s) and the subject DN of the certificate.  This could be caused \
+ because you are connected to a server pretending to be %s:%s.\n\
+ Before accepting this certificate, you should examine the server's \
+ certificate carefully.
  
\ No newline at end of file

--
Gitblit v1.10.0