From 69756f44f935810cff759ff0bcd8803c2a9d83c0 Mon Sep 17 00:00:00 2001
From: jvergara <jvergara@localhost>
Date: Thu, 09 Aug 2007 22:58:02 +0000
Subject: [PATCH] Create a superclass of DsFrameworkCliParser so that command lines that do not have subcommands can use all the logic to parse the arguments associated with certificate management and to generate ApplicationTrustManager objects.
---
opendj-sdk/opends/src/server/org/opends/server/admin/client/cli/SecureConnectionCliParser.java | 736 ++++++++++++++++++++++++++++++
opendj-sdk/opends/src/server/org/opends/server/admin/client/cli/DsFrameworkCliParser.java | 641 --------------------------
opendj-sdk/opends/src/server/org/opends/server/util/args/SubCommandArgumentParser.java | 30 +
3 files changed, 769 insertions(+), 638 deletions(-)
diff --git a/opendj-sdk/opends/src/server/org/opends/server/admin/client/cli/DsFrameworkCliParser.java b/opendj-sdk/opends/src/server/org/opends/server/admin/client/cli/DsFrameworkCliParser.java
index 877ea67..35dd23f 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/admin/client/cli/DsFrameworkCliParser.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/admin/client/cli/DsFrameworkCliParser.java
@@ -22,7 +22,7 @@
* CDDL HEADER END
*
*
- * Portions Copyright 2006-2007 Sun Microsystems, Inc.
+ * Portions Copyright 2007 Sun Microsystems, Inc.
*/
package org.opends.server.admin.client.cli;
@@ -34,145 +34,38 @@
import static org.opends.server.util.ServerConstants.MAX_LINE_WIDTH;
import static org.opends.server.util.StaticUtils.wrapText;
-import java.io.FileInputStream;
import java.io.IOException;
import java.io.OutputStream;
-import java.io.PrintStream;
-import java.security.KeyStore;
-import java.security.KeyStoreException;
-import java.security.NoSuchAlgorithmException;
-import java.security.cert.CertificateException;
import java.util.Comparator;
import java.util.HashSet;
import java.util.Set;
import java.util.SortedSet;
import java.util.TreeSet;
-import java.util.logging.Level;
import java.util.logging.Logger;
import javax.naming.NamingException;
import javax.naming.ldap.InitialLdapContext;
-import javax.net.ssl.KeyManager;
import org.opends.admin.ads.ADSContextException;
-import org.opends.admin.ads.util.ApplicationKeyManager;
-import org.opends.admin.ads.util.ApplicationTrustManager;
import org.opends.admin.ads.util.ConnectionUtils;
import org.opends.server.loggers.debug.DebugTracer;
-import org.opends.server.types.DebugLogLevel;
-import org.opends.server.util.PasswordReader;
-import org.opends.server.util.SelectableCertificateKeyManager;
import org.opends.server.util.args.ArgumentException;
import org.opends.server.util.args.BooleanArgument;
-import org.opends.server.util.args.FileBasedArgument;
-import org.opends.server.util.args.IntegerArgument;
-import org.opends.server.util.args.StringArgument;
import org.opends.server.util.args.SubCommand;
-import org.opends.server.util.args.SubCommandArgumentParser;
import static org.opends.server.admin.client.cli.DsFrameworkCliReturnCode.*;
/**
- * This class will parser CLI arguments.
+ * This class will parse CLI arguments for the dsframework command lines.
*/
-public class DsFrameworkCliParser extends SubCommandArgumentParser
+public class DsFrameworkCliParser extends SecureConnectionCliParser
{
/**
- * End Of Line.
- */
- private String EOL = System.getProperty("line.separator");
-
- /**
* The tracer object for the debug logger.
*/
private static final DebugTracer TRACER = getTracer();
/**
- * The showUsage' global argument.
- */
- private BooleanArgument showUsageArg = null;
-
- /**
- * The 'useSSLArg' global argument.
- */
- private BooleanArgument useSSLArg = null;
-
- /**
- * The 'startTLSArg' global argument.
- */
- private BooleanArgument startTLSArg = null;
-
- /**
- * The 'hostName' global argument.
- */
- private StringArgument hostNameArg = null;
-
- /**
- * The 'port' global argument.
- */
- private IntegerArgument portArg = null;
-
- /**
- * The 'binDN' global argument.
- */
- private StringArgument bindDnArg = null;
-
- /**
- * The 'bindPasswordFile' global argument.
- */
- private FileBasedArgument bindPasswordFileArg = null;
-
- /**
- * The 'bindPassword' global argument.
- */
- private StringArgument bindPasswordArg = null;
-
- /**
- * The 'verbose' global argument.
- */
- private BooleanArgument verboseArg = null;
-
- /**
- * The 'trustAllArg' global argument.
- */
- private BooleanArgument trustAllArg = null;
-
- /**
- * The 'trustStore' global argument.
- */
- private StringArgument trustStorePathArg = null;
-
- /**
- * The 'trustStorePassword' global argument.
- */
- private StringArgument trustStorePasswordArg = null;
-
- /**
- * The 'trustStorePasswordFile' global argument.
- */
- private FileBasedArgument trustStorePasswordFileArg = null;
-
- /**
- * The 'keyStore' global argument.
- */
- private StringArgument keyStorePathArg = null;
-
- /**
- * The 'keyStorePassword' global argument.
- */
- private StringArgument keyStorePasswordArg = null;
-
- /**
- * The 'keyStorePasswordFile' global argument.
- */
- private FileBasedArgument keyStorePasswordFileArg = null;
-
- /**
- * The 'certNicknameArg' global argument.
- */
- private StringArgument certNicknameArg = null;
-
- /**
* The Logger.
*/
static private final Logger LOG =
@@ -273,241 +166,7 @@
}
- /**
- * Initialize Global option.
- *
- * @param outStream
- * The output stream used for the usage.
- * @throws ArgumentException
- * If there is a problem with any of the parameters used
- * to create this argument.
- */
- private void initializeGlobalOption(OutputStream outStream)
- throws ArgumentException
- {
- showUsageArg = new BooleanArgument("showUsage", OPTION_SHORT_HELP,
- OPTION_LONG_HELP, MSGID_DESCRIPTION_SHOWUSAGE);
- addGlobalArgument(showUsageArg);
- setUsageArgument(showUsageArg, outStream);
- useSSLArg = new BooleanArgument("useSSL", OPTION_SHORT_USE_SSL,
- OPTION_LONG_USE_SSL, MSGID_DESCRIPTION_USE_SSL);
- addGlobalArgument(useSSLArg);
-
- startTLSArg = new BooleanArgument("startTLS", OPTION_SHORT_START_TLS,
- OPTION_LONG_START_TLS,
- MSGID_DESCRIPTION_START_TLS);
- addGlobalArgument(startTLSArg);
-
- hostNameArg = new StringArgument("host", OPTION_SHORT_HOST,
- OPTION_LONG_HOST, false, false, true, OPTION_VALUE_HOST, "localhost",
- null, MSGID_DESCRIPTION_HOST);
- addGlobalArgument(hostNameArg);
-
- portArg = new IntegerArgument("port", OPTION_SHORT_PORT, OPTION_LONG_PORT,
- false, false, true, OPTION_VALUE_PORT, 389, null,
- MSGID_DESCRIPTION_PORT);
- addGlobalArgument(portArg);
-
- bindDnArg = new StringArgument("bindDN", OPTION_SHORT_BINDDN,
- OPTION_LONG_BINDDN, false, false, true, OPTION_VALUE_BINDDN,
- "cn=Directory Manager", null, MSGID_DESCRIPTION_BINDDN);
- addGlobalArgument(bindDnArg);
-
- bindPasswordArg = new StringArgument("bindPassword",
- OPTION_SHORT_BINDPWD, OPTION_LONG_BINDPWD, false, false, true,
- OPTION_VALUE_BINDPWD, null, null, MSGID_DESCRIPTION_BINDPASSWORD);
- addGlobalArgument(bindPasswordArg);
-
- bindPasswordFileArg = new FileBasedArgument("bindPasswordFile",
- OPTION_SHORT_BINDPWD_FILE, OPTION_LONG_BINDPWD_FILE, false, false,
- OPTION_VALUE_BINDPWD_FILE, null, null,
- MSGID_DESCRIPTION_BINDPASSWORDFILE);
- addGlobalArgument(bindPasswordFileArg);
-
- trustAllArg = new BooleanArgument("trustAll", 'X', "trustAll",
- MSGID_DESCRIPTION_TRUSTALL);
- addGlobalArgument(trustAllArg);
-
- trustStorePathArg = new StringArgument("trustStorePath",
- OPTION_SHORT_TRUSTSTOREPATH, OPTION_LONG_TRUSTSTOREPATH, false,
- false, true, OPTION_VALUE_TRUSTSTOREPATH, null, null,
- MSGID_DESCRIPTION_TRUSTSTOREPATH);
- addGlobalArgument(trustStorePathArg);
-
- trustStorePasswordArg = new StringArgument("trustStorePassword", null,
- OPTION_LONG_TRUSTSTORE_PWD, false, false, true,
- OPTION_VALUE_TRUSTSTORE_PWD, null, null,
- MSGID_DESCRIPTION_TRUSTSTOREPASSWORD);
- addGlobalArgument(trustStorePasswordArg);
-
- trustStorePasswordFileArg = new FileBasedArgument("truststorepasswordfile",
- OPTION_SHORT_TRUSTSTORE_PWD_FILE, OPTION_LONG_TRUSTSTORE_PWD_FILE,
- false, false, OPTION_VALUE_TRUSTSTORE_PWD_FILE, null, null,
- MSGID_DESCRIPTION_TRUSTSTOREPASSWORD_FILE);
- addGlobalArgument(trustStorePasswordFileArg);
-
- keyStorePathArg = new StringArgument("keyStorePath",
- OPTION_SHORT_KEYSTOREPATH, OPTION_LONG_KEYSTOREPATH, false, false,
- true, OPTION_VALUE_KEYSTOREPATH, null, null,
- MSGID_DESCRIPTION_KEYSTOREPATH);
- addGlobalArgument(keyStorePathArg);
-
- keyStorePasswordArg = new StringArgument("keyStorePassword", null,
- OPTION_LONG_KEYSTORE_PWD, false, false, true,
- OPTION_VALUE_KEYSTORE_PWD, null, null,
- MSGID_DESCRIPTION_KEYSTOREPASSWORD);
- addGlobalArgument(keyStorePasswordArg);
-
- keyStorePasswordFileArg = new FileBasedArgument("keystorepasswordfile",
- OPTION_SHORT_KEYSTORE_PWD_FILE, OPTION_LONG_KEYSTORE_PWD_FILE, false,
- false, OPTION_VALUE_KEYSTORE_PWD_FILE, null, null,
- MSGID_DESCRIPTION_KEYSTOREPASSWORD_FILE);
- addGlobalArgument(keyStorePasswordFileArg);
-
- certNicknameArg = new StringArgument("certnickname", 'N', "certNickname",
- false, false, true, "{nickname}", null, null,
- MSGID_DESCRIPTION_CERT_NICKNAME);
- addGlobalArgument(certNicknameArg);
-
- verboseArg = new BooleanArgument("verbose", 'v', "verbose",
- MSGID_DESCRIPTION_VERBOSE);
- addGlobalArgument(verboseArg);
- }
-
- /**
- * Get the host name which has to be used for the command.
- *
- * @return The host name specified by the command line argument, or
- * the default value, if not specified.
- */
- public String getHostName()
- {
- if (hostNameArg.isPresent())
- {
- return hostNameArg.getValue();
- }
- else
- {
- return hostNameArg.getDefaultValue();
- }
- }
-
- /**
- * Get the port which has to be used for the command.
- *
- * @return The port specified by the command line argument, or the
- * default value, if not specified.
- */
- public String getPort()
- {
- if (portArg.isPresent())
- {
- return portArg.getValue();
- }
- else
- {
- return portArg.getDefaultValue();
- }
- }
-
- /**
- * Get the bindDN which has to be used for the command.
- *
- * @return The bindDN specified by the command line argument, or the
- * default value, if not specified.
- */
- public String getBindDN()
- {
- if (bindDnArg.isPresent())
- {
- return bindDnArg.getValue();
- }
- else
- {
- return bindDnArg.getDefaultValue();
- }
- }
-
-
- /**
- * Get the password which has to be used for the command.
- *
- * @param dn
- * The user DN for which to password could be asked.
- * @param out
- * The input stream to used if we have to prompt to the
- * user.
- * @param err
- * The error stream to used if we have to prompt to the
- * user.
- * @return The password stored into the specified file on by the
- * command line argument, or prompts it if not specified.
- */
- public String getBindPassword(String dn, OutputStream out, OutputStream err)
- {
- if (bindPasswordArg.isPresent())
- {
- String bindPasswordValue = bindPasswordArg.getValue();
- if(bindPasswordValue != null && bindPasswordValue.equals("-"))
- {
- // read the password from the stdin.
- try
- {
- out.write(getMessage(MSGID_LDAPAUTH_PASSWORD_PROMPT, dn).getBytes());
- char[] pwChars = PasswordReader.readPassword();
- bindPasswordValue = new String(pwChars);
- } catch(Exception ex)
- {
- if (debugEnabled())
- {
- TRACER.debugCaught(DebugLogLevel.ERROR, ex);
- }
- try
- {
- err.write(wrapText(ex.getMessage(), MAX_LINE_WIDTH).getBytes());
- err.write(EOL.getBytes());
- }
- catch (IOException e)
- {
- }
- return null;
- }
- }
- return bindPasswordValue;
- }
- else
- if (bindPasswordFileArg.isPresent())
- {
- return bindPasswordFileArg.getValue();
- }
- else
- {
- // read the password from the stdin.
- try
- {
- out.write(getMessage(MSGID_LDAPAUTH_PASSWORD_PROMPT, dn).getBytes());
- char[] pwChars = PasswordReader.readPassword();
- return new String(pwChars);
- }
- catch (Exception ex)
- {
- if (debugEnabled())
- {
- TRACER.debugCaught(DebugLogLevel.ERROR, ex);
- }
- try
- {
- err.write(wrapText(ex.getMessage(), MAX_LINE_WIDTH).getBytes());
- err.write(EOL.getBytes());
- }
- catch (IOException e)
- {
- }
- return null;
- }
- }
- }
/**
* Handle the subcommand.
@@ -541,300 +200,6 @@
return ERROR_UNEXPECTED;
}
- /**
- * Indicate if the verbose mode is required.
- *
- * @return True if verbose mode is required
- */
- public boolean isVerbose()
- {
- if (verboseArg.isPresent())
- {
- return true;
- }
- else
- {
- return false ;
- }
- }
-
-
- /**
- * Indicate if the SSL mode is required.
- *
- * @return True if SSL mode is required
- */
- public boolean useSSL()
- {
- if (useSSLArg.isPresent())
- {
- return true;
- }
- else
- {
- return false ;
- }
- }
-
- /**
- * Indicate if the startTLS mode is required.
- *
- * @return True if startTLS mode is required
- */
- public boolean startTLS()
- {
- if (startTLSArg.isPresent())
- {
- return true;
- }
- else
- {
- return false ;
- }
- }
-
- /**
- * Handle TrustStore.
- *
- * @return The trustStore manager to be used for the command.
- */
- public ApplicationTrustManager getTrustManager()
- {
- ApplicationTrustManager truststoreManager = null ;
- KeyStore truststore = null ;
- if (trustAllArg.isPresent())
- {
- // Running a null TrustManager will force createLdapsContext and
- // createStartTLSContext to use a bindTrustManager.
- return null ;
- }
- else
- if (trustStorePathArg.isPresent())
- {
- try
- {
- FileInputStream fos = new FileInputStream(trustStorePathArg.getValue());
- String trustStorePasswordStringValue = null;
- char[] trustStorePasswordValue = null;
- if (trustStorePasswordArg.isPresent())
- {
- trustStorePasswordStringValue = trustStorePasswordArg.getValue();
- }
- else if (trustStorePasswordFileArg.isPresent())
- {
- trustStorePasswordStringValue = trustStorePasswordFileArg.getValue();
- }
-
- if (trustStorePasswordStringValue != null)
- {
- trustStorePasswordStringValue = System
- .getProperty("javax.net.ssl.trustStorePassword");
- }
-
-
- if (trustStorePasswordStringValue != null)
- {
- trustStorePasswordValue = trustStorePasswordStringValue.toCharArray();
- }
-
- truststore = KeyStore.getInstance(KeyStore.getDefaultType());
- truststore.load(fos, trustStorePasswordValue);
- fos.close();
- }
- catch (KeyStoreException e)
- {
- // Nothing to do: if this occurs we will systematically refuse the
- // certificates. Maybe we should avoid this and be strict, but we are
- // in a best effort mode.
- LOG.log(Level.WARNING, "Error with the truststore", e);
- }
- catch (NoSuchAlgorithmException e)
- {
- // Nothing to do: if this occurs we will systematically refuse the
- // certificates. Maybe we should avoid this and be strict, but we are
- // in a best effort mode.
- LOG.log(Level.WARNING, "Error with the truststore", e);
- }
- catch (CertificateException e)
- {
- // Nothing to do: if this occurs we will systematically refuse the
- // certificates. Maybe we should avoid this and be strict, but we are
- // in a best effort mode.
- LOG.log(Level.WARNING, "Error with the truststore", e);
- }
- catch (IOException e)
- {
- // Nothing to do: if this occurs we will systematically refuse the
- // certificates. Maybe we should avoid this and be strict, but we are
- // in a best effort mode.
- LOG.log(Level.WARNING, "Error with the truststore", e);
- }
- }
- truststoreManager = new ApplicationTrustManager(truststore);
- return truststoreManager;
- }
-
- /**
- * Handle KeyStore.
- *
- * @return The keyStore manager to be used for the command.
- */
- public KeyManager getKeyManager()
- {
- KeyStore keyStore = null;
- String keyStorePasswordStringValue = null;
- char[] keyStorePasswordValue = null;
- if (keyStorePathArg.isPresent())
- {
- try
- {
- FileInputStream fos = new FileInputStream(keyStorePathArg.getValue());
- if (keyStorePasswordArg.isPresent())
- {
- keyStorePasswordStringValue = keyStorePasswordArg.getValue();
- }
- else if (keyStorePasswordFileArg.isPresent())
- {
- keyStorePasswordStringValue = keyStorePasswordFileArg.getValue();
- }
- if (keyStorePasswordStringValue != null)
- {
- keyStorePasswordValue = keyStorePasswordStringValue.toCharArray();
- }
-
- keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
- keyStore.load(fos,keyStorePasswordValue);
- fos.close();
- }
- catch (KeyStoreException e)
- {
- // Nothing to do: if this occurs we will systematically refuse
- // the
- // certificates. Maybe we should avoid this and be strict, but
- // we are in a best effort mode.
- LOG.log(Level.WARNING, "Error with the keystore", e);
- }
- catch (NoSuchAlgorithmException e)
- {
- // Nothing to do: if this occurs we will systematically refuse
- // the
- // certificates. Maybe we should avoid this and be strict, but
- // we are
- // in a best effort mode.
- LOG.log(Level.WARNING, "Error with the keystore", e);
- }
- catch (CertificateException e)
- {
- // Nothing to do: if this occurs we will systematically refuse
- // the
- // certificates. Maybe we should avoid this and be strict, but
- // we are
- // in a best effort mode.
- LOG.log(Level.WARNING, "Error with the keystore", e);
- }
- catch (IOException e)
- {
- // Nothing to do: if this occurs we will systematically refuse
- // the
- // certificates. Maybe we should avoid this and be strict, but
- // we are
- // in a best effort mode.
- LOG.log(Level.WARNING, "Error with the keystore", e);
- }
- char[] password = null;
- if (keyStorePasswordStringValue != null)
- {
- password = keyStorePasswordStringValue.toCharArray();
- }
- ApplicationKeyManager akm = new ApplicationKeyManager(keyStore,password);
- if (certNicknameArg.isPresent())
- {
- return new SelectableCertificateKeyManager(akm, certNicknameArg
- .getValue());
- }
- else
- {
- return akm;
- }
- }
- else
- {
- return null;
- }
- }
-
- /**
- * Indication if provided global options are validate.
- *
- * @param err the stream to be used to print error message.
- * @return return code.
- */
- public int validateGlobalOption(PrintStream err)
- {
- // Couldn't have at the same time bindPassword and bindPasswordFile
- if(bindPasswordArg.isPresent() && bindPasswordFileArg.isPresent())
- {
- int msgID = MSGID_TOOL_CONFLICTING_ARGS;
- String message = getMessage(msgID, bindPasswordArg.getLongIdentifier(),
- bindPasswordFileArg.getLongIdentifier());
- err.println(wrapText(message, MAX_LINE_WIDTH));
- return CONFLICTING_ARGS.getReturnCode();
- }
-
- // Couldn't have at the same time trustAll and
- // trustStore related arg
- if (trustAllArg.isPresent() && trustStorePathArg.isPresent())
- {
- int msgID = MSGID_TOOL_CONFLICTING_ARGS;
- String message = getMessage(msgID, trustAllArg.getLongIdentifier(),
- trustStorePathArg.getLongIdentifier());
- err.println(wrapText(message, MAX_LINE_WIDTH));
- return CONFLICTING_ARGS.getReturnCode();
- }
- if (trustAllArg.isPresent() && trustStorePasswordArg.isPresent())
- {
- int msgID = MSGID_TOOL_CONFLICTING_ARGS;
- String message = getMessage(msgID, trustAllArg.getLongIdentifier(),
- trustStorePasswordArg.getLongIdentifier());
- err.println(wrapText(message, MAX_LINE_WIDTH));
- return CONFLICTING_ARGS.getReturnCode();
- }
- if (trustAllArg.isPresent() && trustStorePasswordFileArg.isPresent())
- {
- int msgID = MSGID_TOOL_CONFLICTING_ARGS;
- String message = getMessage(msgID, trustAllArg.getLongIdentifier(),
- trustStorePasswordFileArg.getLongIdentifier());
- err.println(wrapText(message, MAX_LINE_WIDTH));
- return CONFLICTING_ARGS.getReturnCode();
- }
-
- // Couldn't have at the same time trustStorePasswordArg and
- // trustStorePasswordFileArg
- if (trustStorePasswordArg.isPresent()
- && trustStorePasswordFileArg.isPresent())
- {
- int msgID = MSGID_TOOL_CONFLICTING_ARGS;
- String message = getMessage(msgID, trustStorePasswordArg
- .getLongIdentifier(), trustStorePasswordFileArg.getLongIdentifier());
- err.println(wrapText(message, MAX_LINE_WIDTH));
- return CONFLICTING_ARGS.getReturnCode();
- }
-
- // Couldn't have at the same time startTLSArg and
- // useSSLArg
- if (startTLSArg.isPresent()
- && useSSLArg.isPresent())
- {
- int msgID = MSGID_TOOL_CONFLICTING_ARGS;
- String message = getMessage(msgID, startTLSArg
- .getLongIdentifier(), useSSLArg.getLongIdentifier());
- err.println(wrapText(message, MAX_LINE_WIDTH));
- return CONFLICTING_ARGS.getReturnCode();
- }
-
- return SUCCESSFUL_NOP.getReturnCode();
- }
-
/**
* Get the InitialLdapContext that has to be used for the ADS.
diff --git a/opendj-sdk/opends/src/server/org/opends/server/admin/client/cli/SecureConnectionCliParser.java b/opendj-sdk/opends/src/server/org/opends/server/admin/client/cli/SecureConnectionCliParser.java
new file mode 100644
index 0000000..871340f
--- /dev/null
+++ b/opendj-sdk/opends/src/server/org/opends/server/admin/client/cli/SecureConnectionCliParser.java
@@ -0,0 +1,736 @@
+/*
+ * 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.server.admin.client.cli;
+
+import static org.opends.server.admin.client.cli.DsFrameworkCliReturnCode.*;
+import static org.opends.server.loggers.debug.DebugLogger.debugEnabled;
+import static org.opends.server.loggers.debug.DebugLogger.getTracer;
+import static org.opends.server.messages.MessageHandler.getMessage;
+import static org.opends.server.messages.ToolMessages.*;
+import static org.opends.server.tools.ToolConstants.*;
+import static org.opends.server.util.ServerConstants.MAX_LINE_WIDTH;
+import static org.opends.server.util.StaticUtils.wrapText;
+
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.PrintStream;
+import java.security.KeyStore;
+import java.security.KeyStoreException;
+import java.security.NoSuchAlgorithmException;
+import java.security.cert.CertificateException;
+import java.util.ArrayList;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import javax.net.ssl.KeyManager;
+
+import org.opends.admin.ads.util.ApplicationKeyManager;
+import org.opends.admin.ads.util.ApplicationTrustManager;
+import org.opends.server.loggers.debug.DebugTracer;
+import org.opends.server.types.DebugLogLevel;
+import org.opends.server.util.PasswordReader;
+import org.opends.server.util.SelectableCertificateKeyManager;
+import org.opends.server.util.args.ArgumentException;
+import org.opends.server.util.args.BooleanArgument;
+import org.opends.server.util.args.FileBasedArgument;
+import org.opends.server.util.args.IntegerArgument;
+import org.opends.server.util.args.StringArgument;
+import org.opends.server.util.args.SubCommandArgumentParser;
+
+/**
+ * This is a commodity class that can be used to check the arguments required
+ * to stablish a secure connection in the command line. It can be used
+ * to generate an ApplicationTrustManager object based on the options provided
+ * by the user in the command line.
+ *
+ */
+public abstract class SecureConnectionCliParser extends SubCommandArgumentParser
+{
+ /**
+ * The showUsage' global argument.
+ */
+ protected BooleanArgument showUsageArg = null;
+
+ /**
+ * The 'hostName' global argument.
+ */
+ protected StringArgument hostNameArg = null;
+
+ /**
+ * The 'port' global argument.
+ */
+ protected IntegerArgument portArg = null;
+
+ /**
+ * The 'binDN' global argument.
+ */
+ protected StringArgument bindDnArg = null;
+
+ /**
+ * The 'bindPasswordFile' global argument.
+ */
+ protected FileBasedArgument bindPasswordFileArg = null;
+
+ /**
+ * The 'bindPassword' global argument.
+ */
+ protected StringArgument bindPasswordArg = null;
+
+ /**
+ * The 'verbose' global argument.
+ */
+ protected BooleanArgument verboseArg = null;
+
+ /**
+ * The 'trustAllArg' global argument.
+ */
+ protected BooleanArgument trustAllArg = null;
+
+ /**
+ * The 'trustStore' global argument.
+ */
+ protected StringArgument trustStorePathArg = null;
+
+ /**
+ * The 'trustStorePassword' global argument.
+ */
+ protected StringArgument trustStorePasswordArg = null;
+
+ /**
+ * The 'trustStorePasswordFile' global argument.
+ */
+ protected FileBasedArgument trustStorePasswordFileArg = null;
+
+ /**
+ * The 'keyStore' global argument.
+ */
+ protected StringArgument keyStorePathArg = null;
+
+ /**
+ * The 'keyStorePassword' global argument.
+ */
+ protected StringArgument keyStorePasswordArg = null;
+
+ /**
+ * The 'keyStorePasswordFile' global argument.
+ */
+ protected FileBasedArgument keyStorePasswordFileArg = null;
+
+ /**
+ * The 'certNicknameArg' global argument.
+ */
+ protected StringArgument certNicknameArg = null;
+
+ /**
+ * The 'useSSLArg' global argument.
+ */
+ protected BooleanArgument useSSLArg = null;
+
+ /**
+ * The 'startTLSArg' global argument.
+ */
+ protected BooleanArgument startTLSArg = null;
+
+ /**
+ * The tracer object for the debug logger.
+ */
+ private static final DebugTracer TRACER = getTracer();
+
+ /**
+ * End Of Line.
+ */
+ protected static String EOL = System.getProperty("line.separator");
+
+ /**
+ * The Logger.
+ */
+ static private final Logger LOG =
+ Logger.getLogger(SecureConnectionCliParser.class.getName());
+
+ /**
+ * Creates a new instance of this subcommand argument parser with no
+ * arguments.
+ *
+ * @param mainClassName
+ * The fully-qualified name of the Java class that should
+ * be invoked to launch the program with which this
+ * argument parser is associated.
+ * @param toolDescription
+ * A human-readable description for the tool, which will be
+ * included when displaying usage information.
+ * @param longArgumentsCaseSensitive
+ * Indicates whether subcommand and long argument names
+ * should be treated in a case-sensitive manner.
+ */
+ protected SecureConnectionCliParser(String mainClassName,
+ String toolDescription, boolean longArgumentsCaseSensitive)
+ {
+ super(mainClassName, toolDescription, longArgumentsCaseSensitive);
+ }
+
+ /**
+ * Get the bindDN which has to be used for the command.
+ *
+ * @return The bindDN specified by the command line argument, or the
+ * default value, if not specified.
+ */
+ public String getBindDN()
+ {
+ if (bindDnArg.isPresent())
+ {
+ return bindDnArg.getValue();
+ }
+ else
+ {
+ return bindDnArg.getDefaultValue();
+ }
+ }
+
+
+ /**
+ * Get the password which has to be used for the command.
+ *
+ * @param dn
+ * The user DN for which to password could be asked.
+ * @param out
+ * The input stream to used if we have to prompt to the
+ * user.
+ * @param err
+ * The error stream to used if we have to prompt to the
+ * user.
+ * @return The password stored into the specified file on by the
+ * command line argument, or prompts it if not specified.
+ */
+ public String getBindPassword(String dn, OutputStream out, OutputStream err)
+ {
+ if (bindPasswordArg.isPresent())
+ {
+ String bindPasswordValue = bindPasswordArg.getValue();
+ if(bindPasswordValue != null && bindPasswordValue.equals("-"))
+ {
+ // read the password from the stdin.
+ try
+ {
+ out.write(getMessage(MSGID_LDAPAUTH_PASSWORD_PROMPT, dn).getBytes());
+ char[] pwChars = PasswordReader.readPassword();
+ bindPasswordValue = new String(pwChars);
+ } catch(Exception ex)
+ {
+ if (debugEnabled())
+ {
+ TRACER.debugCaught(DebugLogLevel.ERROR, ex);
+ }
+ try
+ {
+ err.write(wrapText(ex.getMessage(), MAX_LINE_WIDTH).getBytes());
+ err.write(EOL.getBytes());
+ }
+ catch (IOException e)
+ {
+ }
+ return null;
+ }
+ }
+ return bindPasswordValue;
+ }
+ else
+ if (bindPasswordFileArg.isPresent())
+ {
+ return bindPasswordFileArg.getValue();
+ }
+ else
+ {
+ // read the password from the stdin.
+ try
+ {
+ out.write(getMessage(MSGID_LDAPAUTH_PASSWORD_PROMPT, dn).getBytes());
+ char[] pwChars = PasswordReader.readPassword();
+ return new String(pwChars);
+ }
+ catch (Exception ex)
+ {
+ if (debugEnabled())
+ {
+ TRACER.debugCaught(DebugLogLevel.ERROR, ex);
+ }
+ try
+ {
+ err.write(wrapText(ex.getMessage(), MAX_LINE_WIDTH).getBytes());
+ err.write(EOL.getBytes());
+ }
+ catch (IOException e)
+ {
+ }
+ return null;
+ }
+ }
+ }
+
+ /**
+ * Initialize Global option.
+ *
+ * @param outStream
+ * The output stream used for the usage.
+ * @throws ArgumentException
+ * If there is a problem with any of the parameters used
+ * to create this argument.
+ */
+ protected void initializeGlobalOption(OutputStream outStream)
+ throws ArgumentException
+ {
+ showUsageArg = new BooleanArgument("showUsage", OPTION_SHORT_HELP,
+ OPTION_LONG_HELP, MSGID_DESCRIPTION_SHOWUSAGE);
+ addGlobalArgument(showUsageArg);
+ setUsageArgument(showUsageArg, outStream);
+
+ useSSLArg = new BooleanArgument("useSSL", OPTION_SHORT_USE_SSL,
+ OPTION_LONG_USE_SSL, MSGID_DESCRIPTION_USE_SSL);
+ addGlobalArgument(useSSLArg);
+
+ startTLSArg = new BooleanArgument("startTLS", OPTION_SHORT_START_TLS,
+ OPTION_LONG_START_TLS,
+ MSGID_DESCRIPTION_START_TLS);
+ addGlobalArgument(startTLSArg);
+
+ hostNameArg = new StringArgument("host", OPTION_SHORT_HOST,
+ OPTION_LONG_HOST, false, false, true, OPTION_VALUE_HOST, "localhost",
+ null, MSGID_DESCRIPTION_HOST);
+ addGlobalArgument(hostNameArg);
+
+ portArg = new IntegerArgument("port", OPTION_SHORT_PORT, OPTION_LONG_PORT,
+ false, false, true, OPTION_VALUE_PORT, 389, null,
+ MSGID_DESCRIPTION_PORT);
+ addGlobalArgument(portArg);
+
+ bindDnArg = new StringArgument("bindDN", OPTION_SHORT_BINDDN,
+ OPTION_LONG_BINDDN, false, false, true, OPTION_VALUE_BINDDN,
+ "cn=Directory Manager", null, MSGID_DESCRIPTION_BINDDN);
+ addGlobalArgument(bindDnArg);
+
+ bindPasswordArg = new StringArgument("bindPassword",
+ OPTION_SHORT_BINDPWD, OPTION_LONG_BINDPWD, false, false, true,
+ OPTION_VALUE_BINDPWD, null, null, MSGID_DESCRIPTION_BINDPASSWORD);
+ addGlobalArgument(bindPasswordArg);
+
+ bindPasswordFileArg = new FileBasedArgument("bindPasswordFile",
+ OPTION_SHORT_BINDPWD_FILE, OPTION_LONG_BINDPWD_FILE, false, false,
+ OPTION_VALUE_BINDPWD_FILE, null, null,
+ MSGID_DESCRIPTION_BINDPASSWORDFILE);
+ addGlobalArgument(bindPasswordFileArg);
+
+ trustAllArg = new BooleanArgument("trustAll", 'X', "trustAll",
+ MSGID_DESCRIPTION_TRUSTALL);
+ addGlobalArgument(trustAllArg);
+
+ trustStorePathArg = new StringArgument("trustStorePath",
+ OPTION_SHORT_TRUSTSTOREPATH, OPTION_LONG_TRUSTSTOREPATH, false,
+ false, true, OPTION_VALUE_TRUSTSTOREPATH, null, null,
+ MSGID_DESCRIPTION_TRUSTSTOREPATH);
+ addGlobalArgument(trustStorePathArg);
+
+ trustStorePasswordArg = new StringArgument("trustStorePassword", null,
+ OPTION_LONG_TRUSTSTORE_PWD, false, false, true,
+ OPTION_VALUE_TRUSTSTORE_PWD, null, null,
+ MSGID_DESCRIPTION_TRUSTSTOREPASSWORD);
+ addGlobalArgument(trustStorePasswordArg);
+
+ trustStorePasswordFileArg = new FileBasedArgument("truststorepasswordfile",
+ OPTION_SHORT_TRUSTSTORE_PWD_FILE, OPTION_LONG_TRUSTSTORE_PWD_FILE,
+ false, false, OPTION_VALUE_TRUSTSTORE_PWD_FILE, null, null,
+ MSGID_DESCRIPTION_TRUSTSTOREPASSWORD_FILE);
+ addGlobalArgument(trustStorePasswordFileArg);
+
+ keyStorePathArg = new StringArgument("keyStorePath",
+ OPTION_SHORT_KEYSTOREPATH, OPTION_LONG_KEYSTOREPATH, false, false,
+ true, OPTION_VALUE_KEYSTOREPATH, null, null,
+ MSGID_DESCRIPTION_KEYSTOREPATH);
+ addGlobalArgument(keyStorePathArg);
+
+ keyStorePasswordArg = new StringArgument("keyStorePassword", null,
+ OPTION_LONG_KEYSTORE_PWD, false, false, true,
+ OPTION_VALUE_KEYSTORE_PWD, null, null,
+ MSGID_DESCRIPTION_KEYSTOREPASSWORD);
+ addGlobalArgument(keyStorePasswordArg);
+
+ keyStorePasswordFileArg = new FileBasedArgument("keystorepasswordfile",
+ OPTION_SHORT_KEYSTORE_PWD_FILE, OPTION_LONG_KEYSTORE_PWD_FILE, false,
+ false, OPTION_VALUE_KEYSTORE_PWD_FILE, null, null,
+ MSGID_DESCRIPTION_KEYSTOREPASSWORD_FILE);
+ addGlobalArgument(keyStorePasswordFileArg);
+
+ certNicknameArg = new StringArgument("certnickname", 'N', "certNickname",
+ false, false, true, "{nickname}", null, null,
+ MSGID_DESCRIPTION_CERT_NICKNAME);
+ addGlobalArgument(certNicknameArg);
+
+ verboseArg = new BooleanArgument("verbose", 'v', "verbose",
+ MSGID_DESCRIPTION_VERBOSE);
+ addGlobalArgument(verboseArg);
+ }
+
+ /**
+ * Get the host name which has to be used for the command.
+ *
+ * @return The host name specified by the command line argument, or
+ * the default value, if not specified.
+ */
+ public String getHostName()
+ {
+ if (hostNameArg.isPresent())
+ {
+ return hostNameArg.getValue();
+ }
+ else
+ {
+ return hostNameArg.getDefaultValue();
+ }
+ }
+
+ /**
+ * Get the port which has to be used for the command.
+ *
+ * @return The port specified by the command line argument, or the
+ * default value, if not specified.
+ */
+ public String getPort()
+ {
+ if (portArg.isPresent())
+ {
+ return portArg.getValue();
+ }
+ else
+ {
+ return portArg.getDefaultValue();
+ }
+ }
+
+ /**
+ * Indication if provided global options are validate.
+ *
+ * @param err the stream to be used to print error message.
+ * @return return code.
+ */
+ public int validateGlobalOption(PrintStream err)
+ {
+ ArrayList<String> errors = new ArrayList<String>();
+ // Couldn't have at the same time bindPassword and bindPasswordFile
+ if(bindPasswordArg.isPresent() && bindPasswordFileArg.isPresent())
+ {
+ int msgID = MSGID_TOOL_CONFLICTING_ARGS;
+ String message = getMessage(msgID, bindPasswordArg.getLongIdentifier(),
+ bindPasswordFileArg.getLongIdentifier());
+ errors.add(message);
+ }
+
+ // Couldn't have at the same time trustAll and
+ // trustStore related arg
+ if (trustAllArg.isPresent() && trustStorePathArg.isPresent())
+ {
+ int msgID = MSGID_TOOL_CONFLICTING_ARGS;
+ String message = getMessage(msgID, trustAllArg.getLongIdentifier(),
+ trustStorePathArg.getLongIdentifier());
+ errors.add(message);
+ }
+ if (trustAllArg.isPresent() && trustStorePasswordArg.isPresent())
+ {
+ int msgID = MSGID_TOOL_CONFLICTING_ARGS;
+ String message = getMessage(msgID, trustAllArg.getLongIdentifier(),
+ trustStorePasswordArg.getLongIdentifier());
+ errors.add(message);
+ }
+ if (trustAllArg.isPresent() && trustStorePasswordFileArg.isPresent())
+ {
+ int msgID = MSGID_TOOL_CONFLICTING_ARGS;
+ String message = getMessage(msgID, trustAllArg.getLongIdentifier(),
+ trustStorePasswordFileArg.getLongIdentifier());
+ errors.add(message);
+ }
+
+ // Couldn't have at the same time trustStorePasswordArg and
+ // trustStorePasswordFileArg
+ if (trustStorePasswordArg.isPresent()
+ && trustStorePasswordFileArg.isPresent())
+ {
+ int msgID = MSGID_TOOL_CONFLICTING_ARGS;
+ String message = getMessage(msgID, trustStorePasswordArg
+ .getLongIdentifier(), trustStorePasswordFileArg.getLongIdentifier());
+ errors.add(message);
+ }
+
+ // Couldn't have at the same time startTLSArg and
+ // useSSLArg
+ if (startTLSArg.isPresent()
+ && useSSLArg.isPresent())
+ {
+ int msgID = MSGID_TOOL_CONFLICTING_ARGS;
+ String message = getMessage(msgID, startTLSArg
+ .getLongIdentifier(), useSSLArg.getLongIdentifier());
+ errors.add(message);
+ }
+
+ if (errors.size() > 0)
+ {
+ StringBuffer buf = new StringBuffer();
+ for (String error : errors)
+ {
+ if (buf.length() > 0)
+ {
+ buf.append(EOL);
+ }
+ buf.append(error);
+ }
+ err.println(wrapText(buf.toString(), MAX_LINE_WIDTH));
+ return CONFLICTING_ARGS.getReturnCode();
+ }
+
+ return SUCCESSFUL_NOP.getReturnCode();
+ }
+
+ /**
+ * Indicate if the verbose mode is required.
+ *
+ * @return True if verbose mode is required
+ */
+ public boolean isVerbose()
+ {
+ if (verboseArg.isPresent())
+ {
+ return true;
+ }
+ else
+ {
+ return false ;
+ }
+ }
+
+
+ /**
+ * Indicate if the SSL mode is required.
+ *
+ * @return True if SSL mode is required
+ */
+ public boolean useSSL()
+ {
+ if (useSSLArg.isPresent())
+ {
+ return true;
+ }
+ else
+ {
+ return false ;
+ }
+ }
+
+ /**
+ * Indicate if the startTLS mode is required.
+ *
+ * @return True if startTLS mode is required
+ */
+ public boolean startTLS()
+ {
+ if (startTLSArg.isPresent())
+ {
+ return true;
+ }
+ else
+ {
+ return false ;
+ }
+ }
+
+ /**
+ * Handle TrustStore.
+ *
+ * @return The trustStore manager to be used for the command.
+ */
+ public ApplicationTrustManager getTrustManager()
+ {
+ ApplicationTrustManager truststoreManager = null ;
+ KeyStore truststore = null ;
+ if (trustAllArg.isPresent())
+ {
+ // Running a null TrustManager will force createLdapsContext and
+ // createStartTLSContext to use a bindTrustManager.
+ return null ;
+ }
+ else
+ if (trustStorePathArg.isPresent())
+ {
+ try
+ {
+ FileInputStream fos = new FileInputStream(trustStorePathArg.getValue());
+ String trustStorePasswordStringValue = null;
+ char[] trustStorePasswordValue = null;
+ if (trustStorePasswordArg.isPresent())
+ {
+ trustStorePasswordStringValue = trustStorePasswordArg.getValue();
+ }
+ else if (trustStorePasswordFileArg.isPresent())
+ {
+ trustStorePasswordStringValue = trustStorePasswordFileArg.getValue();
+ }
+
+ if (trustStorePasswordStringValue != null)
+ {
+ trustStorePasswordStringValue = System
+ .getProperty("javax.net.ssl.trustStorePassword");
+ }
+
+
+ if (trustStorePasswordStringValue != null)
+ {
+ trustStorePasswordValue = trustStorePasswordStringValue.toCharArray();
+ }
+
+ truststore = KeyStore.getInstance(KeyStore.getDefaultType());
+ truststore.load(fos, trustStorePasswordValue);
+ fos.close();
+ }
+ catch (KeyStoreException e)
+ {
+ // Nothing to do: if this occurs we will systematically refuse the
+ // certificates. Maybe we should avoid this and be strict, but we are
+ // in a best effort mode.
+ LOG.log(Level.WARNING, "Error with the truststore", e);
+ }
+ catch (NoSuchAlgorithmException e)
+ {
+ // Nothing to do: if this occurs we will systematically refuse the
+ // certificates. Maybe we should avoid this and be strict, but we are
+ // in a best effort mode.
+ LOG.log(Level.WARNING, "Error with the truststore", e);
+ }
+ catch (CertificateException e)
+ {
+ // Nothing to do: if this occurs we will systematically refuse the
+ // certificates. Maybe we should avoid this and be strict, but we are
+ // in a best effort mode.
+ LOG.log(Level.WARNING, "Error with the truststore", e);
+ }
+ catch (IOException e)
+ {
+ // Nothing to do: if this occurs we will systematically refuse the
+ // certificates. Maybe we should avoid this and be strict, but we are
+ // in a best effort mode.
+ LOG.log(Level.WARNING, "Error with the truststore", e);
+ }
+ }
+ truststoreManager = new ApplicationTrustManager(truststore);
+ return truststoreManager;
+ }
+
+ /**
+ * Handle KeyStore.
+ *
+ * @return The keyStore manager to be used for the command.
+ */
+ public KeyManager getKeyManager()
+ {
+ KeyStore keyStore = null;
+ String keyStorePasswordStringValue = null;
+ char[] keyStorePasswordValue = null;
+ if (keyStorePathArg.isPresent())
+ {
+ try
+ {
+ FileInputStream fos = new FileInputStream(keyStorePathArg.getValue());
+ if (keyStorePasswordArg.isPresent())
+ {
+ keyStorePasswordStringValue = keyStorePasswordArg.getValue();
+ }
+ else if (keyStorePasswordFileArg.isPresent())
+ {
+ keyStorePasswordStringValue = keyStorePasswordFileArg.getValue();
+ }
+ if (keyStorePasswordStringValue != null)
+ {
+ keyStorePasswordValue = keyStorePasswordStringValue.toCharArray();
+ }
+
+ keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
+ keyStore.load(fos,keyStorePasswordValue);
+ fos.close();
+ }
+ catch (KeyStoreException e)
+ {
+ // Nothing to do: if this occurs we will systematically refuse
+ // the
+ // certificates. Maybe we should avoid this and be strict, but
+ // we are in a best effort mode.
+ LOG.log(Level.WARNING, "Error with the keystore", e);
+ }
+ catch (NoSuchAlgorithmException e)
+ {
+ // Nothing to do: if this occurs we will systematically refuse
+ // the
+ // certificates. Maybe we should avoid this and be strict, but
+ // we are
+ // in a best effort mode.
+ LOG.log(Level.WARNING, "Error with the keystore", e);
+ }
+ catch (CertificateException e)
+ {
+ // Nothing to do: if this occurs we will systematically refuse
+ // the
+ // certificates. Maybe we should avoid this and be strict, but
+ // we are
+ // in a best effort mode.
+ LOG.log(Level.WARNING, "Error with the keystore", e);
+ }
+ catch (IOException e)
+ {
+ // Nothing to do: if this occurs we will systematically refuse
+ // the
+ // certificates. Maybe we should avoid this and be strict, but
+ // we are
+ // in a best effort mode.
+ LOG.log(Level.WARNING, "Error with the keystore", e);
+ }
+ char[] password = null;
+ if (keyStorePasswordStringValue != null)
+ {
+ password = keyStorePasswordStringValue.toCharArray();
+ }
+ ApplicationKeyManager akm = new ApplicationKeyManager(keyStore,password);
+ if (certNicknameArg.isPresent())
+ {
+ return new SelectableCertificateKeyManager(akm, certNicknameArg
+ .getValue());
+ }
+ else
+ {
+ return akm;
+ }
+ }
+ else
+ {
+ return null;
+ }
+ }
+}
diff --git a/opendj-sdk/opends/src/server/org/opends/server/util/args/SubCommandArgumentParser.java b/opendj-sdk/opends/src/server/org/opends/server/util/args/SubCommandArgumentParser.java
index 6b5d36b..0bc42fa 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/util/args/SubCommandArgumentParser.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/util/args/SubCommandArgumentParser.java
@@ -518,6 +518,36 @@
globalArgumentList.add(argument);
}
+ /**
+ * Removes the provided argument from the set of global arguments handled by
+ * this parser.
+ *
+ * @param argument The argument to be removed.
+ */
+ protected void removeGlobalArgument(Argument argument)
+ {
+ String argumentName = argument.getName();
+ globalArgumentMap.remove(argumentName);
+
+ Character shortID = argument.getShortIdentifier();
+ if (shortID != null)
+ {
+ globalShortIDMap.remove(shortID);
+ }
+
+ String longID = argument.getLongIdentifier();
+ if (longID != null)
+ {
+ if (! longArgumentsCaseSensitive)
+ {
+ longID = toLowerCase(longID);
+ }
+
+ globalLongIDMap.remove(longID);
+ }
+
+ globalArgumentList.remove(argument);
+ }
/**
--
Gitblit v1.10.0