/*
* 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 Geoffrey Said.
* Portions created by Geoffrey Said are Copyright (C) 2006.
* All Rights Reserved.
*
* Contributor(s): Geoffrey Said
*/
package com.slamd.scripting.tftp;
import com.slamd.job.JobClass;
import com.slamd.tftp.TFTPClient;
import com.slamd.scripting.engine.Argument;
import com.slamd.scripting.engine.Method;
import com.slamd.scripting.engine.ScriptException;
import com.slamd.scripting.engine.Variable;
import com.slamd.scripting.general.BooleanVariable;
import com.slamd.scripting.general.IntegerVariable;
import com.slamd.scripting.general.StringVariable;
import com.slamd.stat.StatTracker;
/**
* Defines a SLAMD variable that can be included in scripts to simulate a TFTP
* client. The TFTP client provides the following methods:
*
* <UL>
* <LI> setServerIP(String serverIP): Sets the TFTP Server IP. This method
* those not return anything.
* <LI> setFileName(String fileName): Assigns the file name to download from
* the TFTP server. This method those not return anything.
* <LI> setDataTransferMode(String mode): Indicates how the data should be
* transfered ie Binary, ASCII, and mail. This method those not return
* anything.
* <LI> setNumberOfRetries(int numberOfRetries): Affects how many
* times the client will try to retransmit the current packet. This
* method those not return anything.
* <LI> setTimeout(int timeout): Sets the timeout, in milliseconds, to wait
* for a packet to arrive over the network. This method those not return
* anything.
* <LI> getServerIP(): Returns the server IP as a string. The default is
* <I>"127.0.0.1"</I>.
* <LI> getFileName(): Returns a string containing the file name to fetch.
* The default is <I>"filename"</I>.
* <LI> getDataTransferMode(): Returns the current transfer mode stored as a
* string. The default is <I>"octet"</I>.
* <LI> getNumberOfRetries(): Returns the number of retries as an integer.
* The default is <I>3</I>.
* <LI> getTimeout(): Returns an integer with the timeout, in milliseconds.
* The default is <I>3000</I> which is equivalent to 3 seconds.
* <LI> getErrorMessage(): When an error message is received by the client, the
* text portion is stored in the <CODE>errorMessage</CODE> variable. This
* method returns the content of the variable as a string. If no error
* packet has been received, the message <I>"No error message"</I> is
* returned.
* <LI> getFetchedDataLength(): Returns the total length of the downloaded file.
* It returns 0 if nothing has been fetched yet.
* <LI> getFile(): Fetches a file from the TFTP server. Returns 0 if
* everything worked fine, 1 if an error packet was received, 2 if the
* maximum number of retries has been exceeded, and 3 if a
* TFTPClientException has been thrown by the TFTP client.
* <LI> enableStatisticsCollection(): Enables the gathering of statistical
* information.
* <LI> disableStatisticsCollection(): Disables the gathering of statistical
* information.
* <LI> isStatisticsEnabled(): Returns true if statistics collection is
* enabled and false if not.
* <LI> areWeCollectingNow(): Returns true if the client is currently
* collecting statistical information and false if not.
* </UL>
*
* @author 2X Geoffrey Said
*/
public class TFTPClientVariable extends Variable
{
// Static public variables declaration
/**
* The name that will be used to identify the tftp client variable.
*/
public static final String TFTP_CLIENT_VARIABLE_TYPE = "tftpclient";
/**
* The name of the method that is used to set the TFTP server IP address.
*/
public static final String SET_SERVER_IP_METHOD_NAME = "setserverip";
/**
* The number of the <I>setServerIP</I> method.
*/
public static final int SET_SERVER_IP_METHOD_NUMBER = 0;
/**
* The name of the method that is used to set the file name to fetch.
*/
public static final String SET_FILE_NAME_METHOD_NAME = "setfilename";
/**
* The number of the <I>setFileName</I> method.
*/
public static final int SET_FILE_NAME_METHOD_NUMBER = 1;
/**
* The name of the method that is used to set the data transfer mode.
*/
public static final String SET_DATA_TRANSFER_MODE_METHOD_NAME =
"setdatatransfermode";
/**
* The number of the <I>setDataTransferMode</I> method.
*/
public static final int SET_DATA_TRANSFER_MODE_METHOD_NUMBER = 2;
/**
* The name of the method that is used to set the number of retransmissions.
*/
public static final String SET_NUMBER_OF_RETRIES_METHOD_NAME =
"setnumberofretries";
/**
* The number of the <I>setNumberOfRetries</I> method.
*/
public static final int SET_NUMBER_OF_RETRIES_METHOD_NUMBER = 3;
/**
* The name of the method that is used to set the timeout, in milliseconds,
* to wait for a packet on the network before a retransmission is necessary.
*/
public static final String SET_TIMEOUT_METHOD_NAME = "settimeout";
/**
* The number of the <I>setTimout</I> method.
*/
public static final int SET_TIMEOUT_METHOD_NUMBER = 4;
/**
* The name of the method that is used to know the, currently set, TFTP server IP.
*/
public static final String GET_SERVER_IP_METHOD_NAME = "getserverip";
/**
* The number of the <I>getServerIP</I> method.
*/
public static final int GET_SERVER_IP_METHOD_NUMBER = 5;
/**
* The name of the method that is used to return the file name to fetch.
*/
public static final String GET_FILE_NAME_METHOD_NAME = "getfilename";
/**
* The number of the <I>getFileName</I> method.
*/
public static final int GET_FILE_NAME_METHOD_NUMBER = 6;
/**
* The name of the method that is used to know the download transfer mode.
*/
public static final String GET_DATA_TRANSFER_MODE_METHOD_NAME =
"getdatatransfermode";
/**
* The number of the <I>getDataTransferMode</I> method.
*/
public static final int GET_DATA_TRANSFER_MODE_METHOD_NUMBER = 7;
/**
* The name of the method that is used to determine the number of retries
* that is currently set.
*/
public static final String GET_NUMBER_OF_RETRIES_METHOD_NAME =
"getnumberofretries";
/**
* The number of the <I>getNumberOfRetries</I> method.
*/
public static final int GET_NUMBER_OF_RETRIES_METHOD_NUMBER = 8;
/**
* The name of the method that is used to determine the current timeout
* setting.
*/
public static final String GET_TIMEOUT_METHOD_NAME = "gettimeout";
/**
* The number of the <I>getTimeout</I> method.
*/
public static final int GET_TIMEOUT_METHOD_NUMBER = 9;
/**
* The name of the method that is used to retreive the error message
* when a file transfer failes.
*/
public static final String GET_ERROR_MESSAGE_METHOD_NAME =
"geterrormessage";
/**
* The number of the <I>getErrorMessage</I> method.
*/
public static final int GET_ERROR_MESSAGE_METHOD_NUMBER = 10;
/**
* The name of the method that is used to return the length of
* any downloaded data.
*/
public static final String GET_FETCHED_DATA_LENGTH_METHOD_NAME =
"getfetcheddatalength";
/**
* The number of the <I>getFetchedDataLength</I> method.
*/
public static final int GET_FETCHED_DATA_LENGTH_METHOD_NUMBER = 11;
/**
* The name of the method that is used to download a file from a particular
* TFTP server.
*/
public static final String GET_FILE_METHOD_NAME = "getfile";
/**
* The number of the <I>getFile</I> method.
*/
public static final int GET_FILE_METHOD_NUMBER = 12;
/**
* The name of the method that is used to enable the automatic collection
* of statistical data.
*/
public static final String ENABLE_STATISTICS_COLLECTION_METHOD_NAME =
"enablestatisticscollection";
/**
* The number of the <I>enableStatisticsCollection</I> method.
*/
public static final int ENABLE_STATISTICS_COLLECTION_METHOD_NUMBER = 13;
/**
* The name of the method that is used to disable the gathering of
* statistical information.
*/
public static final String DISABLE_STATISTICS_COLLECTION_METHOD_NAME =
"disablestatisticscollection";
/**
* The number of the <I>disableStatisticsCollection</I> method.
*/
public static final int DISABLE_STATISTICS_COLLECTION_METHOD_NUMBER = 14;
/**
* The name of the method that is used to determine if the automatic
* collection of statistical data is enabled.
*/
public static final String IS_STATISTICS_ENABLED_METHOD_NAME =
"isstatisticsenabled";
/**
* The number of the <I>isStatisticsEnabled</I> method.
*/
public static final int IS_STATISTICS_ENABLED_METHOD_NUMBER = 15;
/**
* The name of the method that is used to check whether the object is
* currently collection statistical information.
*/
public static final String ARE_WE_COLLECTING_NOW_METHOD_NAME =
"arewecollectingnow";
/**
* the number of the <I>areWeCollectingNow</I> method.
*/
public static final int ARE_WE_COLLECTING_NOW_METHOD_NUMBER = 16;
/**
* The set of method provided by the TFTP client variable.
*/
public static final Method[] TFTP_CLIENT_VARIABLE_METHODS = new Method[]
{
new Method(SET_SERVER_IP_METHOD_NAME,
new String[] {StringVariable.STRING_VARIABLE_TYPE}, null),
new Method(SET_FILE_NAME_METHOD_NAME,
new String[] {StringVariable.STRING_VARIABLE_TYPE}, null),
new Method(SET_DATA_TRANSFER_MODE_METHOD_NAME,
new String[] {StringVariable.STRING_VARIABLE_TYPE}, null),
new Method(SET_NUMBER_OF_RETRIES_METHOD_NAME,
new String[] {IntegerVariable.INTEGER_VARIABLE_TYPE}, null),
new Method(SET_TIMEOUT_METHOD_NAME,
new String[] {IntegerVariable.INTEGER_VARIABLE_TYPE}, null),
new Method(GET_SERVER_IP_METHOD_NAME,
new String[0], StringVariable.STRING_VARIABLE_TYPE),
new Method(GET_FILE_NAME_METHOD_NAME,
new String[0], StringVariable.STRING_VARIABLE_TYPE),
new Method(GET_DATA_TRANSFER_MODE_METHOD_NAME,
new String[0], StringVariable.STRING_VARIABLE_TYPE),
new Method(GET_NUMBER_OF_RETRIES_METHOD_NAME,
new String[0], IntegerVariable.INTEGER_VARIABLE_TYPE),
new Method(GET_TIMEOUT_METHOD_NAME,
new String[0], IntegerVariable.INTEGER_VARIABLE_TYPE),
new Method(GET_ERROR_MESSAGE_METHOD_NAME,
new String[0], StringVariable.STRING_VARIABLE_TYPE),
new Method(GET_FETCHED_DATA_LENGTH_METHOD_NAME,
new String[0], IntegerVariable.INTEGER_VARIABLE_TYPE),
new Method(GET_FILE_METHOD_NAME,
new String[0], IntegerVariable.INTEGER_VARIABLE_TYPE),
new Method(ENABLE_STATISTICS_COLLECTION_METHOD_NAME,
new String[0], null),
new Method(DISABLE_STATISTICS_COLLECTION_METHOD_NAME, new String[0], null),
new Method(IS_STATISTICS_ENABLED_METHOD_NAME, new String[0],
BooleanVariable.BOOLEAN_VARIABLE_TYPE),
new Method(ARE_WE_COLLECTING_NOW_METHOD_NAME, new String[0],
BooleanVariable.BOOLEAN_VARIABLE_TYPE)
};
// The actual TFTP client that is going to handle all requests
private TFTPClient tftpClient;
// The variables associated with statistical information gathering
private int collectionInterval;
private String clientID;
private String threadID;
private StatTracker[] statTrackers;
// A String to hold the last failure message
private String failureMessage;
/**
* Creates a new TFTP client variable with no name, to be used only when
* creating a variable with <CODE>Class.newInstance()</CODE>, and only when
* <CODE>setName()</CODE> is called after that to set the name.
*
* @throws ScriptException if a problem occurs while initializing the new
* variable.
*/
public TFTPClientVariable() throws ScriptException
{
tftpClient = new TFTPClient();
failureMessage = null;
statTrackers = new StatTracker[0];
}
/**
* Creates a new TFTP client variable that is set to fetch files from
* the specified TFTP server IP.
*
* @param serverIP a string containing the TFTP server IP.
*
* @throws ScriptException if a problem occurs while initializing the new
* variable.
*/
public TFTPClientVariable(String serverIP) throws ScriptException
{
tftpClient = new TFTPClient(serverIP);
failureMessage = null;
statTrackers = new StatTracker[0];
}
/**
* Creates a new TFTP client variable that is set to fetch the file stored
* in the <CODE>filename</CODE> variable from the TFTP server IP specified
* in the <CODE>serverIP</CODE> variable.
*
* @param serverIP a string containing the TFTP server IP.
* @param fileName a string containing the file name.
* @throws ScriptException if a problem occurs while initializing the new
* variable.
*/
public TFTPClientVariable(String serverIP, String fileName)
throws ScriptException
{
tftpClient = new TFTPClient(serverIP, fileName);
failureMessage = null;
statTrackers = new StatTracker[0];
}
/*
* Stores the passed message in the failureMessage variable
*/
private void setFailureMessage(String message)
{
this.failureMessage = message;
}
/**
* Returns any failure messages stored in the <CODE>failureMessage</CODE> variable.
*
* @return a string containing the error message.
*/
public String getFailureMessage()
{
return failureMessage;
}
/**
* Returns the type of the current variable.
*
* @return a string with the variable type.
*/
@Override()
public String getVariableTypeName()
{
return TFTP_CLIENT_VARIABLE_TYPE;
}
/**
* Returns the set of methods that this client offers.
*
* @return a method array with all the method signitures.
*/
@Override()
public Method[] getMethods()
{
return TFTP_CLIENT_VARIABLE_METHODS;
}
/**
* Checks for the passed method name in the methods array.
*
* @param methodName the name of the method.
*
* @return true if the name is in the methods array,
* false if the name those not match any method.
*/
@Override()
public boolean hasMethod(String methodName)
{
for (int x = 0; x < TFTP_CLIENT_VARIABLE_METHODS.length; x++)
{
if (TFTP_CLIENT_VARIABLE_METHODS[x].getName().equals(methodName))
return true;
}
return false;
}
/**
* Returns the method number as found in the methods array.
*
* @param methodName the name of the method.
* @param argumentTypes the method's arguments.
*
* @return -1 if the passed method's signiture those not match any stored
* in the methods array.
* the index position of the matched method.
*/
@Override()
public int getMethodNumber(String methodName, String[] argumentTypes)
{
for (int x = 0; x < TFTP_CLIENT_VARIABLE_METHODS.length; x++)
{
if (TFTP_CLIENT_VARIABLE_METHODS[x].hasSignature(methodName,
argumentTypes))
return x;
}
return -1;
}
/**
* Returns the return type of the specified method.
*
* @param methodName the name of the method.
* @param argumentTypes the method's arguments.
*
* @return null if the method is not found,
* the return type as a string.
*/
@Override()
public String getReturnTypeForMethod(String methodName,
String[] argumentTypes)
{
int position = 0;
position = getMethodNumber(methodName, argumentTypes);
if (position >= 0)
return TFTP_CLIENT_VARIABLE_METHODS[position].getReturnType();
else
return null;
}
/**
* Executes the specified method, using the provided variables as arguments
* to the method, and makes the return value available to the caller.
*
* @param lineNumber the line number in the script where the method call
* occurred.
* @param methodNumber the method number of the method to execute.
* @param arguments the set of arguments to use for the method.
*
* @return the value returned from the method, or null if it does not
* return anything.
*
* @throws ScriptException if the specified method does not exist, or if a
* problem occurs while attempting to execute it.
*/
@Override()
public Variable executeMethod(int lineNumber, int methodNumber,
Argument[] arguments) throws ScriptException
{
StringVariable sv;
IntegerVariable iv;
int returnCode;
switch (methodNumber)
{
case SET_SERVER_IP_METHOD_NUMBER:
sv = (StringVariable) arguments[0].getArgumentValue();
tftpClient.setServerIP(sv.getStringValue());
return null;
case SET_FILE_NAME_METHOD_NUMBER:
sv = (StringVariable) arguments[0].getArgumentValue();
tftpClient.setFileName(sv.getStringValue());
return null;
case SET_DATA_TRANSFER_MODE_METHOD_NUMBER:
sv = (StringVariable) arguments[0].getArgumentValue();
tftpClient.setDataTransferMode(sv.getStringValue());
return null;
case SET_NUMBER_OF_RETRIES_METHOD_NUMBER:
iv = (IntegerVariable) arguments[0].getArgumentValue();
tftpClient.setNumberOfRetries(iv.getIntValue());
return null;
case SET_TIMEOUT_METHOD_NUMBER:
iv = (IntegerVariable) arguments[0].getArgumentValue();
tftpClient.setTimeout(iv.getIntValue());
return null;
case GET_SERVER_IP_METHOD_NUMBER:
return new StringVariable(tftpClient.getServerIP());
case GET_FILE_NAME_METHOD_NUMBER:
return new StringVariable(tftpClient.getFileName());
case GET_DATA_TRANSFER_MODE_METHOD_NUMBER:
return new StringVariable(tftpClient.getDataTransferMode());
case GET_NUMBER_OF_RETRIES_METHOD_NUMBER:
return new IntegerVariable(tftpClient.getNumberOfRetries());
case GET_TIMEOUT_METHOD_NUMBER:
return new IntegerVariable(tftpClient.getTimeout());
case GET_ERROR_MESSAGE_METHOD_NUMBER:
return new StringVariable(getFailureMessage());
case GET_FETCHED_DATA_LENGTH_METHOD_NUMBER:
return new IntegerVariable(tftpClient.getFetchedDataLength());
case GET_FILE_METHOD_NUMBER:
try
{
returnCode = tftpClient.getFile();
switch (returnCode)
{
case 1:
setFailureMessage(tftpClient.getErrorMessage());
return new IntegerVariable(1);
case 2:
setFailureMessage("Client: timeout occured!");
return new IntegerVariable(2);
default:
return new IntegerVariable(0);
}
}
catch(Exception exception)
{
setFailureMessage(exception.toString());
return new IntegerVariable(3);
}
case ENABLE_STATISTICS_COLLECTION_METHOD_NUMBER:
tftpClient.enableStatisticsCollection(clientID, threadID,
collectionInterval);
return null;
case DISABLE_STATISTICS_COLLECTION_METHOD_NUMBER:
tftpClient.disableStatisticsCollection();
return null;
case IS_STATISTICS_ENABLED_METHOD_NUMBER:
return new BooleanVariable(tftpClient.isStatisticsEnabled());
case ARE_WE_COLLECTING_NOW_METHOD_NUMBER:
return new BooleanVariable(tftpClient.areWeCollectingNow());
default:
throw new ScriptException(lineNumber, "There is no method "
+ methodNumber + " defined for "
+ getArgumentType() + " variables.");
}
}
/**
* Assigns the value of the provided argument to this variable.
*
* @param argument the argument whose value is to be assigned to this
* variable.
*
* @throws ScriptException if the argument cannot be assigned to this
* variable.
*/
@Override()
public void assign(Argument argument) throws ScriptException
{
if (! argument.getArgumentType().equals(TFTP_CLIENT_VARIABLE_TYPE))
{
throw new ScriptException("Cannot assign argument of type "
+ argument.getArgumentType()
+ " to variable of type "
+ TFTP_CLIENT_VARIABLE_TYPE);
}
TFTPClientVariable tftpcv =
(TFTPClientVariable) argument.getArgumentValue();
tftpClient = tftpcv.tftpClient;
failureMessage = tftpcv.failureMessage;
}
/**
* Returns a string representation of the current object.
*
* @return a string with the variable's data.
*/
public String getValueAsString()
{
String message;
message = "This is the current status of the TFTP Client:\n"
+ "\tTFTP Server IP: \t" + tftpClient.getServerIP() + '\n'
+ "\tFile to download: \t" + tftpClient.getFileName() + '\n'
+ "\tData transfer mode: \t"
+ tftpClient.getDataTransferMode()
+ '\n' + "\tTimeout of: \t" + tftpClient.getTimeout()
+ " milliseconds\n" + "\tNumber of Retries: \t"
+ tftpClient.getNumberOfRetries();
return message;
}
/**
* Returns the statistical information.
*
* @return a statistical tracker array with all the trackers.
*/
@Override()
public StatTracker[] getStatTrackers()
{
return statTrackers;
}
/**
* Collects information to be able to start the statistical trackers.
*
* @param jobClass the job class that is currently associated with
* the trackers.
*/
@Override()
public void startStatTrackers(JobClass jobClass)
{
clientID = jobClass.getClientID();
threadID = jobClass.getThreadID();
collectionInterval = jobClass.getCollectionInterval();
}
/**
* Calls the TFTP client method <CODE>getStatTrackers</CODE> to stop the
* trackers and stores them in the <CODE>statTrackers</CODE> array.
*/
@Override()
public void stopStatTrackers()
{
statTrackers = tftpClient.getStatTrackers();
}
}