/*
* 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
* 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-2010 Sun Microsystems, Inc.
* Portions Copyright 2011-2013 ForgeRock AS
* Portions Copyright 2011 profiq s.r.o.
*/
/**
* This class provides a very simple mechanism for installing the OpenDS
* Directory Service. It performs the following tasks:
* <UL>
* <LI>Checks if the server is already installed and running</LI>
* <LI>Ask the user what base DN should be used for the data</LI>
* <LI>Ask the user whether to create the base entry, or to import LDIF</LI>
* <LI>Ask the user for the administration port and make sure it's available
* </LI>
* <LI>Ask the user for the LDAP port and make sure it's available</LI>
* <LI>Ask the user for the default root DN and password</LI>
* <LI>Ask the user to enable SSL or not and for the type of certificate that
* the server must use</LI>
* <LI>Ask the user if they want to start the server when done installing</LI>
* </UL>
*/
{
/** Prefix for log files. */
/** Suffix for log files. */
/**
* The enumeration containing the different return codes that the command-line
* can have.
*/
enum ErrorReturnCode
{
/**
* Successful setup.
*/
/**
* We did no have an error but the setup was not executed (displayed
* version or usage).
*/
/**
* Unexpected error (potential bug).
*/
/**
* Cannot parse arguments or data provided by user is not valid.
*/
/**
* Error server already installed.
*/
/**
* Error initializing server.
*/
/**
* The user failed providing password (for the keystore for instance).
*/
/**
* The user cancelled the setup.
*/
/**
* The user doesn't accept the license.
*/
/**
* Incompatible java version.
*/
private int returnCode;
{
this.returnCode = returnCode;
}
/**
* Get the corresponding return code value.
*
* @return The corresponding return code value.
*/
public int getReturnCode()
{
return returnCode;
}
}
/**
* Enumeration describing the different answer that the user can provide
* when we ask to finalize the setup. Note that the code associated
* correspond to the order in the confirmation menu that is displayed at the
* end of the setup in interactive mode.
*/
private enum ConfirmCode
{
// Continue with the install
// Provide information again
// Display equivalent command-line
// Cancel the install
private int returnCode;
{
this.returnCode = returnCode;
}
/**
* Get the corresponding return code value.
*
* @return The corresponding return code value.
*/
public int getReturnCode()
{
return returnCode;
}
}
/**
* The maximum number of times that we should ask the user to provide the
* password to access to a keystore.
*/
// Different variables we use when the user decides to provide data again.
/**
* The Logger.
*/
/** The argument parser. */
/**
* Constructor for the InstallDS object.
*
* @param out the print stream to use for standard output.
* @param err the print stream to use for standard error.
* @param in the input stream to use for standard input.
*/
{
}
/**
* The main method for the InstallDS CLI tool.
*
* @param args the command-line arguments provided to this program.
*/
{
}
/**
* Parses the provided command-line arguments and uses that information to
* run the setup tool.
*
* @param args the command-line arguments provided to this program.
*
* @return The error code.
*/
{
}
/**
* Parses the provided command-line arguments and uses that information to
* run the setup tool.
*
* @param args The command-line arguments provided to this
* program.
* @param outStream The output stream to use for standard output, or
* <CODE>null</CODE> if standard output is not
* needed.
* @param errStream The output stream to use for standard error, or
* <CODE>null</CODE> if standard error is not
* needed.
* @param inStream The input stream to use for standard input.
* @return The error code.
*/
{
try {
} catch (Throwable t) {
t.printStackTrace();
}
}
/**
* Parses the provided command-line arguments and uses that information to
* run the setup CLI.
*
* @param args the command-line arguments provided to this program.
* @return the return code (SUCCESSFUL, USER_DATA_ERROR or BUG).
*/
{
try
{
}
catch (ArgumentException ae)
{
}
// Validate user provided data
try
{
}
catch (ArgumentException ae)
{
println();
}
// Delete the log file that does not contain any information. The test only
// mode is called several times by the setup script and if we do not remove
// it we have a lot of empty log files.
{
try
{
}
catch (Throwable t)
{
"the set-java-home file in test only mode: "+t, t);
}
// Test that we are running a compatible java 1.6 version.
try
{
}
catch (IncompatibleVersionException ive)
{
}
}
// If either the showUsage or testOnly or version arguments were provided,
// then we're done.
if (argParser.usageOrVersionDisplayed() ||
{
}
try
{
}
catch (InitializationException ie)
{
}
// Check license
if (LicenseFile.exists())
{
// If the user asks for acceptLicense, license is displayed
// and automatically accepted.
{
// No-prompt arg automatically rejects the license.
{
while (true)
{
try
{
{
.getReturnCode();
}
{
LicenseFile.setApproval(true);
break;
}
else
{
.get());
}
}
catch (IOException e)
{
.get());
}
}
}
else
{
}
}
else
{
LicenseFile.setApproval(true);
}
}
boolean userApproved = false;
while (!userApproved)
{
try
{
if (isInteractive())
{
}
else
{
}
}
catch (UserDataException ude)
{
{
}
else
{
}
}
boolean promptAgain = true;
if (!isInteractive())
{
userApproved = true;
}
else
{
}
while (isInteractive() && promptAgain)
{
promptAgain = false;
switch (confirm)
{
case CONTINUE:
userApproved = true;
break;
case CANCEL:
promptAgain = true;
break;
default:
// Reset the arguments
try
{
}
catch (Throwable t)
{
}
userApproved = false;
}
}
if (!isInteractive())
{
userApproved = true;
}
}
new ProgressUpdateListener() {
{
}
}
});
// Use this instead a call to Installation to avoid to launch a new JVM
// just to retrieve a path.
if (SetupUtils.isWindows())
{
}
else
{
}
{
}
else
{
}
}
/**
* Checks if the server is installed or not.
* @throws InitializationException if the server is already installed and
* configured or if the user did not accept to overwrite the existing
* databases.
*/
{
{
if (isInteractive())
{
try
{
{
}
}
catch (CLIException ce)
{
}
}
else
{
}
}
else if (installStatus.isInstalled())
{
null);
}
}
/**
* {@inheritDoc}
*/
public boolean isQuiet()
{
}
/**
* {@inheritDoc}
*/
public boolean isInteractive()
{
}
/**
* {@inheritDoc}
*/
public boolean isMenuDrivenMode() {
return true;
}
/**
* {@inheritDoc}
*/
public boolean isScriptFriendly() {
return false;
}
/**
* {@inheritDoc}
*/
public boolean isAdvancedMode() {
return false;
}
/**
* {@inheritDoc}
*/
public boolean isVerbose() {
}
/**
* This method updates the contents of a UserData object with what the user
* specified in the command-line. It assumes that it is being called in no
* prompt mode.
* @param uData the UserData object.
* @throws UserDataException if something went wrong checking the data.
*/
throws UserDataException
{
// Check the validity of the directory manager DNs
try
{
{
}
}
catch (Exception e)
{
}
// Check the validity of the base DNs
{
}
{
try
{
}
catch (Exception e)
{
}
}
try
{
{
}
{
{
}
}
}
catch (ArgumentException ae)
{
}
{
// Check that the files exist
{
{
}
}
{
}
if (rejectedFile != null)
{
{
}
}
if (skippedFile != null)
{
{
skippedFile));
}
}
}
{
}
{
}
else
{
}
// Check that the security data provided is valid.
int ldapsPort = -1;
try
{
}
catch (ArgumentException ae)
{
}
{
}
{
}
{
{
}
}
{
{
}
}
{
{
}
}
{
{
}
}
else
{
}
{
throw new UserDataException(null,
}
}
{
{
}
}
{
{
}
}
/**
* This method updates the contents of a UserData object with what the user
* specified in the command-line. If the user did not provide explicitly some
* data or if the provided data is not valid, it prompts the user to provide
* it.
* @param uData the UserData object to be updated.
* @throws UserDataException if the user did not manage to provide the
* keystore password after a certain number of tries.
*/
{
}
/**
* This method updates the contents of a UserData object with what the user
* specified in the command-line for the Directory Manager parameters.
* If the user did not provide explicitly some data or if the provided data is
* not valid, it prompts the user to provide it.
* @param uData the UserData object to be updated.
* @throws UserDataException if something went wrong checking the data.
*/
throws UserDataException
{
true);
int nTries = 0;
{
if (nTries >= CONFIRMATION_MAX_TRIES)
{
throw new UserDataException(null,
}
// Prompt for password and confirm.
{
{
println();
println();
}
}
{
}
else
{
println();
}
nTries++;
}
}
/**
* This method returns a list of DNs. It checks that the provided list of
* DNs actually contain some values. If no valid values are found it prompts
* the user to provide a valid DN.
* @param arg the Argument that the user provided to specify the DNs.
* @param promptMsg the prompt message to be displayed.
* @param includeLineBreak whether to include a line break before the first
* prompt or not.
* @return a list of valid DNs.
* @throws UserDataException if something went wrong checking the data.
*/
{
boolean usedProvided = false;
boolean firstPrompt = true;
int nTries = 0;
{
if (nTries >= CONFIRMATION_MAX_TRIES)
{
throw new UserDataException(null,
}
boolean prompted = false;
{
if (firstPrompt && includeLineBreak)
{
println();
}
try
{
firstPrompt = false;
prompted = true;
}
catch (CLIException ce)
{
}
}
else
{
usedProvided = true;
}
{
try
{
{
}
}
catch (Exception e)
{
}
}
{
println();
}
nTries++;
}
return dns;
}
/**
* This method updates the contents of a UserData object with what the user
* specified in the command-line for the administration connector, LDAP and
* JMX port parameters.
* If the user did not provide explicitly some data or if the provided data is
* not valid, it prompts the user to provide it.
* Note: this method does not update nor check the LDAPS port.
* @param uData the UserData object to be updated.
*/
{
// Determine the LDAP port number.
// Determine the Admin Connector port number.
int adminConnectorPort =
{
}
else
{
}
}
/**
* This method returns a valid port value. It checks that the provided
* argument contains a valid port. If a valid port is not found it prompts
* the user to provide a valid port.
* @param portArg the Argument that the user provided to specify the port.
* @param promptMsg the prompt message to be displayed.
* @param usedPorts the list of ports the user provided before for other
* connection handlers.
* @param includeLineBreak whether to include a line break before the first
* prompt or not.
* @return a valid port number.
*/
boolean includeLineBreak)
{
int portNumber = -1;
boolean usedProvided = false;
boolean firstPrompt = true;
while (portNumber == -1)
{
try
{
boolean prompted = false;
{
int defaultValue = -1;
{
}
if (firstPrompt && includeLineBreak)
{
println();
}
portNumber = -1;
while (portNumber == -1)
{
try
{
}
catch (CLIException ce)
{
portNumber = -1;
}
}
prompted = true;
firstPrompt = false;
}
else
{
usedProvided = true;
}
{
{
if (prompted || includeLineBreak)
{
println();
}
{
println();
}
portNumber = -1;
}
}
if (portNumber != -1)
{
{
println();
portNumber = -1;
}
}
}
catch (ArgumentException ae)
{
}
}
return portNumber;
}
/**
* This method returns what the user specified in the command-line for the
* base DN and data import parameters. If the user did not provide explicitly
* some data or if the provided data is not valid, it prompts the user to
* provide it.
*
* @return the NewSuffixOptions telling how to import data
* @throws UserDataException
* if something went wrong checking the data.
*/
throws UserDataException
{
boolean prompt = true;
{
println();
try
{
true);
}
catch (CLIException ce)
{
prompt = true;
}
}
if (!prompt)
{
}
else
{
// Check the validity of the base DNs
}
return dataOptions;
}
{
{
// Check that the files exist
{
{
}
else
{
}
}
{
println();
}
while (importLDIFFiles.isEmpty())
{
println();
try
{
{
println();
}
else
{
}
}
catch (CLIException ce)
{
}
}
if (rejectedFile != null)
{
{
println();
println();
try
{
}
catch (CLIException ce)
{
}
}
}
if (skippedFile != null)
{
{
println();
println();
try
{
}
catch (CLIException ce)
{
}
}
}
}
{
}
{
int numUsers;
try
{
}
catch (ArgumentException ae)
{
println();
}
numUsers);
}
else
{
final int POPULATE_TYPE_BASE_ONLY = 1;
final int POPULATE_TYPE_LEAVE_EMPTY = 2;
final int POPULATE_TYPE_IMPORT_FROM_LDIF = 3;
final int POPULATE_TYPE_GENERATE_SAMPLE_DATA = 4;
};
{
}
if (lastResetPopulateOption == null)
{
}
else
{
switch (lastResetPopulateOption)
{
case LEAVE_DATABASE_EMPTY:
break;
case IMPORT_FROM_LDIF_FILE:
break;
break;
default:
}
}
int populateType;
try
{
if (m.isSuccess())
{
populateType = m.getValue();
}
else
{
// Should never happen.
throw new RuntimeException();
}
}
catch (CLIException ce)
{
}
{
while (importLDIFFiles.isEmpty())
{
println();
try
{
{
}
else
{
println();
}
}
catch (CLIException ce)
{
}
}
if (rejectedFile != null)
{
{
println();
println();
try
{
}
catch (CLIException ce)
{
}
}
}
if (skippedFile != null)
{
{
println();
println();
try
{
}
catch (CLIException ce)
{
}
}
}
}
else if (populateType == POPULATE_TYPE_GENERATE_SAMPLE_DATA)
{
int defaultValue;
if (lastResetNumEntries == null)
{
defaultValue = 2000;
}
else
{
}
numUsers);
}
else if (populateType == POPULATE_TYPE_LEAVE_EMPTY)
{
}
else if (populateType == POPULATE_TYPE_BASE_ONLY)
{
}
else
{
throw new IllegalStateException("Unexpected populateType: "+
}
}
return dataOptions;
}
/**
* This method returns what the user specified in the command-line for the
* security parameters. If the user did not provide explicitly some data or if
* the provided data is not valid, it prompts the user to provide it.
*
* @param uData
* the current UserData object.
* @return the {@link SecurityOptions} to be used when starting the server
* @throws UserDataException
* if the user did not manage to provide the keystore password after
* a certain number of tries.
*/
throws UserDataException
{
// Check that the security data provided is valid.
boolean enableSSL = false;
boolean enableStartTLS = false;
int ldapsPort = -1;
{
}
// Ask to enable SSL
{
println();
try
{
false;
if (enableSSL)
{
}
}
catch (CLIException ce)
{
}
}
else
{
enableSSL = true;
}
// Ask to enable Start TLS
{
println();
try
{
lastResetEnableStartTLS : false;
}
catch (CLIException ce)
{
}
}
else
{
enableStartTLS = true;
}
{
}
{
}
{
}
{
}
{
}
else
{
if (!enableSSL && !enableStartTLS)
{
// If the user did not want to enable SSL or start TLS do not ask
// to create a certificate.
}
else
{
final int SELF_SIGNED = 1;
final int JKS = 2;
final int JCEKS = 3;
final int PKCS12 = 4;
final int PKCS11 = 5;
};
{
}
if (lastResetCertType == null)
{
}
else
{
switch (lastResetCertType)
{
case JKS:
break;
case JCEKS:
break;
case PKCS11:
break;
case PKCS12:
break;
default:
}
}
int certType;
try
{
if (m.isSuccess())
{
}
else
{
// Should never happen.
throw new RuntimeException();
}
}
catch (CLIException ce)
{
}
if (certType == SELF_SIGNED)
{
}
{
}
{
}
{
}
{
}
else
{
}
}
}
return securityOptions;
}
/**
* This method returns what the user specified in the command-line for the
* Windows Service parameters. If the user did not provide explicitly the
* data, it prompts the user to provide it.
*
* @return whether windows service should be enabled
*/
private boolean promptIfRequiredForWindowsService()
{
boolean enableService = false;
// If we are in Windows ask if the server must run as a windows service.
if (SetupUtils.isWindows())
{
{
enableService = true;
}
else
{
println();
try
{
false : lastResetEnableWindowsService;
}
catch (CLIException ce)
{
}
}
}
return enableService;
}
/**
* This method returns what the user specified in the command-line for the
* Directory Manager parameters. If the user did not provide explicitly the
* data, it prompts the user to provide it.
*
* @return whether server should be started
*/
private boolean promptIfRequiredForStartServer()
{
boolean startServer = false;
{
println();
try
{
true : lastResetStartServer;
}
catch (CLIException ce)
{
startServer = true;
}
}
return startServer;
}
/**
* Checks that the provided parameters are valid to access an existing
* key store. This method adds the encountered errors to the provided
* list of Message. It also adds the alias (nicknames) found to the provided
* list of String.
* @param type the type of key store.
* @param path the path of the key store.
* @param pwd the password (PIN) to access the key store.
* @param certNickname the certificate nickname that we are looking for (or
* null if we just one to get the one that is in the key store).
* @param errorMessages the list that will be updated with the errors
* encountered.
* @param nicknameList the list that will be updated with the nicknames found
* in the key store.
*/
public static void checkCertificateInKeystore(
{
boolean errorWithPath = false;
{
if (!f.exists())
{
errorWithPath = true;
}
else if (!f.isFile())
{
errorWithPath = true;
}
}
if (!errorWithPath)
{
try
{
switch (type)
{
case JKS:
certManager = new CertificateManager(
path,
pwd);
break;
case JCEKS:
certManager = new CertificateManager(
path,
pwd);
break;
case PKCS12:
certManager = new CertificateManager(
path,
pwd);
break;
case PKCS11:
certManager = new CertificateManager(
pwd);
break;
default:
}
{
// Could not retrieve any certificate
switch (type)
{
case JKS:
break;
case JCEKS:
break;
case PKCS12:
break;
case PKCS11:
break;
default:
}
}
else if (certManager.hasRealAliases())
{
", ");
if (certNickname != null)
{
// Check if the certificate alias is in the list.
boolean found = false;
{
}
if (!found)
{
aliasString));
}
}
{
aliasString));
}
}
}
catch (KeyStoreException ke)
{
// issue OPENDJ-18, related to JDK bug
{
}
else
{
// Could not access to the key store: because the password is no good,
// because the provided file is not a valid key store, etc.
switch (type)
{
case JKS:
break;
case JCEKS:
break;
case PKCS12:
break;
case PKCS11:
break;
default:
}
}
}
}
}
/**
* Creates a SecurityOptions object that corresponds to the provided
* parameters. If the parameters are not valid, it prompts the user to
* provide them.
* @param type the keystore type.
* @param enableSSL whether to enable SSL or not.
* @param enableStartTLS whether to enable StartTLS or not.
* @param ldapsPort the LDAPS port to use.
* @return a SecurityOptions object that corresponds to the provided
* parameters (or to what the user provided after being prompted).
* @throws UserDataException if the user did not manage to provide the
* keystore password after a certain number of tries.
*/
{
{
{
}
}
switch (type)
{
case JKS:
if (defaultPathValue == null)
{
}
break;
case JCEKS:
if (defaultPathValue == null)
{
}
break;
case PKCS11:
pathPrompt = null;
break;
case PKCS12:
if (defaultPathValue == null)
{
}
break;
default:
throw new IllegalStateException(
"Called promptIfRequiredCertificate with invalid type: "+type);
}
boolean firstTry = true;
int nPasswordPrompts = 0;
{
boolean prompted = false;
{
println();
}
{
{
println();
try
{
}
catch (CLIException ce)
{
path = "";
}
prompted = true;
{
if (!errorMessages.isEmpty())
{
// Reset password: this might be a new keystore
}
}
}
}
{
if (!prompted)
{
println();
}
{
{
throw new UserDataException(null,
}
pwd = readPassword(
nPasswordPrompts ++;
}
}
{
if (!prompted)
{
println();
}
}
firstTry = false;
}
{
}
switch (type)
{
case JKS:
break;
case JCEKS:
break;
case PKCS12:
break;
case PKCS11:
break;
default:
throw new IllegalStateException(
"Called createSecurityOptionsPrompting with invalid type: "+type);
}
return securityOptions;
}
/**
* Tells if any of the error messages provided corresponds to a problem
* with the key store path.
* @param msgs the messages to analyze.
* @return <CODE>true</CODE> if any of the error messages provided corresponds
* to a problem with the key store path and <CODE>false</CODE> otherwise.
*/
public static boolean containsKeyStorePathErrorMessage(
{
boolean found = false;
{
{
found = true;
break;
}
}
return found;
}
/**
* Tells if any of the error messages provided corresponds to a problem
* with the key store password.
* @param msgs the messages to analyze.
* @return <CODE>true</CODE> if any of the error messages provided corresponds
* to a problem with the key store password and <CODE>false</CODE> otherwise.
*/
public static boolean containsKeyStorePasswordErrorMessage(
{
boolean found = false;
{
{
found = true;
break;
}
}
return found;
}
/**
* Tells if any of the error messages provided corresponds to a problem
* with the certificate nickname.
* @param msgs the messages to analyze.
* @return <CODE>true</CODE> if any of the error messages provided corresponds
* to a problem with the certificate nickname and <CODE>false</CODE>
* otherwise.
*/
public static boolean containsCertNicknameErrorMessage(
{
boolean found = false;
{
{
found = true;
break;
}
}
return found;
}
/**
* Tells if the error messages provided corresponds to a problem with the
* password tries.
* @param msg the message to analyze.
* @return <CODE>true</CODE> if the error message provided corresponds to a
* problem with the password tries and <CODE>false</CODE> otherwise.
*/
{
}
/**
* Interactively prompts (on standard output) the user to provide an integer
* value. The answer provided must be parseable as an integer, and may be
* required to be within a given set of bounds. It will keep prompting until
* an acceptable value is given.
*
* @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</CODE> if
* there should not be a default and the user must
* explicitly provide a value.
* @param lowerBound The lower bound that should be enforced, or
* <CODE>null</CODE> if there is none.
* @param upperBound The upper bound that should be enforced, or
* <CODE>null</CODE> if there is none.
*
* @return The <CODE>int</CODE> value read from the user input.
*/
{
int returnValue = -1;
while (returnValue == -1)
{
String s;
try
{
}
catch (CLIException ce)
{
s = "";
}
if (s.equals(""))
{
if (defaultValue == null)
{
println();
}
else
{
}
}
else
{
try
{
{
println();
}
{
println();
}
else
{
}
}
catch (NumberFormatException nfe)
{
println();
}
}
}
return returnValue;
}
/**
* Prompts the user to accept on the certificates that appears on the list
* and returns the chosen certificate nickname.
* @param nicknames the list of certificates the user must choose from.
* @return the chosen certificate nickname.
*/
{
{
{
try
{
{
nickname = n;
break;
}
}
catch (CLIException ce)
{
}
}
}
return nickname;
}
/**
* It displays the information provided by the user.
* @param uData the UserData that the user provided.
*/
{
println();
println();
{
};
{
};
int maxWidth = 0;
{
}
{
{
{
if (j != 0)
{
for (int k=0; k <= maxWidth; k++)
{
}
}
else
{
{
}
}
sb = new StringBuilder();
}
}
}
println();
if (uData.getStartServer())
{
}
else
{
}
{
if (uData.getEnableWindowsService())
{
}
else
{
}
}
}
{
println();
println();
}
/**
* This method asks the user to confirm to continue the setup. It basically
* displays the information provided by the user and at the end proposes a
* menu with the different options to choose from.
* @return the answer provided by the user: cancel setup, continue setup or
* provide information again.
*/
{
println();
println();
};
int i=0;
{
i++;
}
try
{
if (m.isSuccess())
{
returnValue = m.getValue();
}
else
{
// Should never happen.
throw new RuntimeException();
}
}
catch (CLIException ce)
{
}
return returnValue;
}
{
try
{
if (jmxPort != -1)
{
}
{
}
if (lastResetPopulateOption ==
{
}
else if (lastResetPopulateOption ==
{
}
if (sec.getEnableSSL())
{
}
{
}
else
{
}
}
catch (Throwable t)
{
}
}
{
{
}
else
{
println();
{
try
{
}
catch (CLIException ce)
{
}
}
}
return hostName;
}
/**
* Returns the timeout to be used to connect in milliseconds. The method
* must be called after parsing the arguments.
* @return the timeout to be used to connect in milliseconds. Returns
* {@code 0} if there is no timeout.
*/
private int getConnectTimeout()
{
return argParser.getConnectTimeout();
}
}