/* * Sun Public License * * The contents of this file are subject to the Sun Public License Version * 1.0 (the "License"). You may not use this file except in compliance with * the License. A copy of the License is available at http://www.sun.com/ * * The Original Code is the SLAMD Distributed Load Generation Engine. * The Initial Developer of the Original Code is Neil A. Wilson. * Portions created by Neil A. Wilson are Copyright (C) 2004-2010. * Some preexisting portions Copyright (C) 2002-2006 Sun Microsystems, Inc. * All Rights Reserved. * * Contributor(s): Neil A. Wilson */ package com.slamd.tools; import java.io.FileInputStream; import java.io.IOException; import java.util.Iterator; import java.util.Properties; import com.slamd.client.ClientMessageWriter; import com.slamd.clientmanager.ClientManager; /** * This class provides an implementation of a client manager that may be used to * automate the process of connecting and disconnecting clients to and from the * SLAMD server. * * * @author Neil A. Wilson */ public class CommandLineClientManager implements ClientMessageWriter { /** * The name of the configuration property that specifies the address of the * SLAMD server. */ public static final String PROPERTY_SLAMD_ADDRESS = "SLAMD_ADDRESS"; /** * The name of the configuration property that specifies the client manager * port for the SLAMD server. */ public static final String PROPERTY_SLAMD_MANAGER_PORT = "SLAMD_MANAGER_PORT"; /** * The name of the configuration property that specifies the client address. */ public static final String PROPERTY_CLIENT_ADDRESS = "CLIENT_ADDRESS"; /** * The name of the configuration property that specifies the client ID. */ public static final String PROPERTY_CLIENT_ID = "CLIENT_ID"; /** * The name of the configuration property that specifies whether to use SSL. */ public static final String PROPERTY_USE_SSL = "USE_SSL"; /** * The name of the configuration property that specifies whether to blindly * trust any certificate. */ public static final String PROPERTY_BLIND_TRUST = "BLIND_TRUST"; /** * The name of the configuration property that specifies the path to the SSL * keystore. */ public static final String PROPERTY_KEY_STORE = "SSL_KEY_STORE"; /** * The name of the configuration property that specifies the password for the * SSL keystore. */ public static final String PROPERTY_KEY_PASS = "SSL_KEY_PASS"; /** * The name of the configuration property that specifies the path to the SSL * trust store. */ public static final String PROPERTY_TRUST_STORE = "SSL_TRUST_PASS"; /** * The name of the configuration property that specifies the password for the * SSL trust store. */ public static final String PROPERTY_TRUST_PASS = "SSL_TRUST_PASS"; /** * The name of the configuration property that specifies whether to enable * verbose mode. */ public static final String PROPERTY_VERBOSE = "VERBOSE_MODE"; /** * The name of the configuration property that specifies how many clients to * automatically create when connecting to the SLAMD server. */ public static final String PROPERTY_AUTO_CREATE_CLIENTS = "AUTO_CREATE_CLIENTS"; /** * The name of the configuration property that specifies the maximum number of * concurrent client instances that should be allowed by the client manager. */ public static final String PROPERTY_MAX_CLIENTS = "MAX_CLIENTS"; /** * The default command that will be used to start the client manager if none * is provided. Note that this does not apply to Windows systems, as they * require a different default command. */ public static final String DEFAULT_START_COMMAND = "./start_client.sh"; /** * The default command that will be used to start the client manager on * Windows systems if none is provided. */ public static final String DEFAULT_START_COMMAND_WINDOWS = "start_client.bat"; // Indicates whether the client manager should blindly trust any certificate // provided by the SLAMD server. private boolean blindTrust = false; // Indicates whether this client manager should communicate over SSL. private boolean useSSL = false; // Indicates whether this client manager is operating in verbose mode. private boolean verboseMode = false; // The number of client instances that should be automatically created // whenever the client manager establishes a connection to the SLAMD server. private int autoCreateClients = 0; // The maximum number of clients that may be started using this client // manager. private int maxClients = 0; // The port number to use to contact the SLAMD server. private int port = 3001; // The local address that the client should use. private String clientAddress = null; // The client ID for this client. private String clientID = null; // The address of the SLAMD server. private String host = null; // The location of the JSSE key store. private String sslKeyStore = null; // The password required to access the JSSE key store. private String sslKeyStorePassword = null; // The location of the JSSE trust store. private String sslTrustStore = null; // The password required to access the JSSE trust store. private String sslTrustStorePassword = null; // The command to use to start the SLAMD client application. private String startCommand = DEFAULT_START_COMMAND; /** * Creates a new instance of this client manager. * * @param args The command-line arguments provided to this client manager. */ public static void main(String[] args) { new CommandLineClientManager(args); } /** * Creates a new instance of this client manager. * * @param args The command-line arguments provided to this client manager. */ public CommandLineClientManager(String[] args) { if (System.getProperty("os.name").toLowerCase().contains("windows")) { startCommand = DEFAULT_START_COMMAND_WINDOWS; } // See if a configuration file was specified. If so, then process it. for (int i=0; i < args.length; i++) { if (args[i].equals("-f")) { processConfigFile(args[++i]); break; } } // Iterate through the command-line arguments and use them to set values // for the configuration parameters. for (int i=0; i < args.length; i++) { if (args[i].equals("-h")) { host = args[++i]; } else if (args[i].equals("-p")) { port = Integer.parseInt(args[++i]); } else if (args[i].equals("-C")) { clientAddress = args[++i]; } else if (args[i].equals("-n")) { clientID = args[++i]; } else if (args[i].equals("-c")) { startCommand = args[++i]; } else if (args[i].equals("-A")) { autoCreateClients = Integer.parseInt(args[++i]); } else if (args[i].equals("-m")) { maxClients = Integer.parseInt(args[++i]); } else if (args[i].equals("-v")) { verboseMode = true; } else if (args[i].equals("-S")) { useSSL = true; } else if (args[i].equals("-B")) { blindTrust = true; } else if (args[i].equals("-k")) { sslKeyStore = args[++i]; } else if (args[i].equals("-K")) { sslKeyStorePassword = args[++i]; } else if (args[i].equals("-t")) { sslTrustStore = args[++i]; } else if (args[i].equals("-T")) { sslTrustStorePassword = args[++i]; } else if (args[i].equals("-H")) { displayUsage(); return; } else if (args[i].equals("-f")) { // Already handled this. i++; } else { System.err.println("ERROR: Unrecognized parameter \"" + args[i] + '"'); displayUsage(); return; } } // Make sure that at least the host was specified. if (host == null) { System.err.println("ERROR: No host specified (use \"-h\")"); displayUsage(); return; } // Create the new client manager instance. ClientManager clientManager = new ClientManager(clientID, clientAddress, host, port, useSSL, blindTrust, sslKeyStore, sslKeyStorePassword, sslTrustStore, sslTrustStorePassword, maxClients, startCommand, this); clientManager.setAutoCreateClients(autoCreateClients); clientManager.run(); } /** * Processes the contents of the specified config file. * * @param configFile The path to the configuration file to process. */ public void processConfigFile(String configFile) { Properties properties = new Properties(); try { properties.load(new FileInputStream(configFile)); } catch (IOException ioe) { System.err.println("ERROR: Unable to load properties file \"" + configFile + "\": " + ioe); System.exit(1); } Iterator keys = properties.keySet().iterator(); while (keys.hasNext()) { String name = (String) keys.next(); String value = properties.getProperty(name, null); if (value == null) { continue; } if (name.equals(PROPERTY_SLAMD_ADDRESS)) { host = value; } else if (name.equals(PROPERTY_SLAMD_MANAGER_PORT)) { port = Integer.parseInt(value); } else if (name.equals(PROPERTY_CLIENT_ADDRESS)) { clientAddress = value; } else if (name.equals(PROPERTY_CLIENT_ID)) { clientID = value; } else if (name.equals(PROPERTY_USE_SSL)) { if (value.equalsIgnoreCase("true") || value.equalsIgnoreCase("yes") || value.equalsIgnoreCase("on") || value.equalsIgnoreCase("1")) { useSSL = true; } else if (value.equalsIgnoreCase("false") || value.equalsIgnoreCase("no") || value.equalsIgnoreCase("off") || value.equalsIgnoreCase("0")) { useSSL = false; } else { System.err.println("ERROR: Cannot interpret the value of the " + PROPERTY_USE_SSL + " property as a Boolean."); System.exit(1); } } else if (name.equals(PROPERTY_BLIND_TRUST)) { if (value.equalsIgnoreCase("true") || value.equalsIgnoreCase("yes") || value.equalsIgnoreCase("on") || value.equalsIgnoreCase("1")) { blindTrust = true; } else if (value.equalsIgnoreCase("false") || value.equalsIgnoreCase("no") || value.equalsIgnoreCase("off") || value.equalsIgnoreCase("0")) { blindTrust = false; } else { System.err.println("ERROR: Cannot interpret the value of the " + PROPERTY_BLIND_TRUST + " property as a Boolean."); System.exit(1); } } else if (name.equals(PROPERTY_KEY_STORE)) { sslKeyStore = value; } else if (name.equals(PROPERTY_KEY_PASS)) { sslKeyStorePassword = value; } else if (name.equals(PROPERTY_TRUST_STORE)) { sslTrustStore = value; } else if (name.equals(PROPERTY_TRUST_PASS)) { sslTrustStorePassword = value; } else if (name.equals(PROPERTY_AUTO_CREATE_CLIENTS)) { autoCreateClients = Integer.parseInt(value); } else if (name.equals(PROPERTY_MAX_CLIENTS)) { maxClients = Integer.parseInt(value); } else if (name.equals(PROPERTY_VERBOSE)) { if (value.equalsIgnoreCase("true") || value.equalsIgnoreCase("yes") || value.equalsIgnoreCase("on") || value.equalsIgnoreCase("1")) { verboseMode = true; } else if (value.equalsIgnoreCase("false") || value.equalsIgnoreCase("no") || value.equalsIgnoreCase("off") || value.equalsIgnoreCase("0")) { verboseMode = false; } else { System.err.println("ERROR: Cannot interpret the value of the " + PROPERTY_VERBOSE + " property as a Boolean."); System.exit(1); } } } } /** * Displays the usage information for this program on standard error. */ public static void displayUsage() { System.err.println("USAGE: java CommandLineClientManager [options]"); System.err.println(" where [options] include:"); System.err.println("-h {host} -- The address of the SLAMD server"); System.err.println("-p {port} -- The port of the client manager listener"); System.err.println("-C {addr} -- The local source address to use for " + "the client"); System.err.println("-n {id} -- The client ID to use for the client"); System.err.println("-m {num} -- The maximum number of clients to allow"); System.err.println("-c {cmd} -- The command to start the SLAMD client"); System.err.println("-S -- Indicates that SSL should be enabled"); System.err.println("-B -- Indicates that the client should " + "blindly trust any certificate"); System.err.println("-t {file} -- The path to the certificate trust store"); System.err.println("-T {pw} -- The password for the certificate trust " + "store"); System.err.println("-k {file} -- The path to the certificate key store"); System.err.println("-K {pw} -- The password for the certificate key " + "store"); System.err.println("-v -- Use verbose mode"); System.err.println("-H -- Display this usage information"); } /** * Writes the provided message to this message writer. * * @param message The message to be written. */ public void writeMessage(String message) { System.out.println(message); } /** * Writes the provided message if this message writer is operating in verbose * mode. * * @param message The message to be written. */ public void writeVerbose(String message) { if (verboseMode) { System.out.println(message); } } /** * Indicates whether this message writer is operating in verbose mode. * * @return <CODE>true</CODE> if this message writer is operating in verbose * mode, or <CODE>false</CODE> if not. */ public boolean usingVerboseMode() { return verboseMode; } }