/* * 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.scripting.http; import java.util.ArrayList; import com.slamd.http.HTTPResponse; 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.StringArrayVariable; import com.slamd.scripting.general.StringVariable; /** * This class defines a variable that can be used to encapsulate a response from * an HTTP server. An HTTP response variable offers the following methods: * * <UL> * <LI>getContentLength() -- Returns an integer that contains the value of the * "content-length" header for this response, or -1 if no content-length * header is available.</LI> * <LI>getContentType() -- Returns a string that contains the value of the * "content-type" header for this response.</LI> * <LI>getDataAsString() -- Returns a string that contains the string representation of the actual data contained in the response.</LI> * <LI>getHeader(string name) -- Returns a string that contains the value of * the header with the specified name.</LI> * <LI>getHeaderNames() -- Returns a string array that contains the names of * the headers associated with this response.</LI> * <LI>getHeaderValues(string name) -- Returns a string array that contains * the values of the header with the specified name.</LI> * <LI>getHTMLDocument() -- Returns an HTMLDocument containing the data * associated with this response.</LI> * <LI>getResponseMessage() -- Returns a string value that contains the * response message provided by the server.</LI> * <LI>getProtocolVersion() -- Returns a string value that contains the * protocol version used by the server in the response.</LI> * <LI>getStatusCode() -- Returns an integer that contains the status code for * this response.</LI> * <LI>isNull() -- Indicates whether this represents a null response.</LI> * </UL> * * * @author Neil A. Wilson */ public class HTTPResponseVariable extends Variable { /** * The name that will be used for the data type of HTTP response variables. */ public static final String HTTP_RESPONSE_VARIABLE_TYPE = "httpresponse"; /** * The name of the method used to retrieve the value of the Content-Length * header. */ public static final String GET_CONTENT_LENGTH_METHOD_NAME = "getcontentlength"; /** * The method number for the "getContentLength" method. */ public static final int GET_CONTENT_LENGTH_METHOD_NUMBER = 0; /** * The name of the method used to retrieve the value of the Content-Type * header. */ public static final String GET_CONTENT_TYPE_METHOD_NAME = "getcontenttype"; /** * The method number for the "getContentType" method. */ public static final int GET_CONTENT_TYPE_METHOD_NUMBER = 1; /** * The name of the method used to retrieve a string representation of the * data associated with this response. */ public static final String GET_DATA_AS_STRING_METHOD_NAME = "getdataasstring"; /** * The method number for the "getDataAsString" method. */ public static final int GET_DATA_AS_STRING_METHOD_NUMBER = 2; /** * The name of the method used to retrieve the value of the requested header. */ public static final String GET_HEADER_METHOD_NAME = "getheader"; /** * The method number for the "getHeader" method. */ public static final int GET_HEADER_METHOD_NUMBER = 3; /** * The name of the method used to retrieve the names of the headers associated * this this response. */ public static final String GET_HEADER_NAMES_METHOD_NAME = "getheadernames"; /** * The method number for the "getHeaderNames" method. */ public static final int GET_HEADER_NAMES_METHOD_NUMBER = 4; /** * The name of the method used to retrieve the values of the requested header. */ public static final String GET_HEADER_VALUES_METHOD_NAME = "getheadervalues"; /** * The method number for the "getHeaderValues" method. */ public static final int GET_HEADER_VALUES_METHOD_NUMBER = 5; /** * The name of the method used to retrieve the HTML document associated with * this response. */ public static final String GET_HTML_DOCUMENT_METHOD_NAME = "gethtmldocument"; /** * The method number for the "getHTMLDocument" method. */ public static final int GET_HTML_DOCUMENT_METHOD_NUMBER = 6; /** * The name of the method used to retrieve the response message for this * response. */ public static final String GET_RESPONSE_MESSAGE_METHOD_NAME = "getresponsemessage"; /** * The method number for the "getResponseMessage" method. */ public static final int GET_RESPONSE_MESSAGE_METHOD_NUMBER = 7; /** * The name of the method used to retrieve the protocol version string for * this response. */ public static final String GET_PROTOCOL_VERSION_METHOD_NAME = "getprotocolversion"; /** * The method number for the "getProtocolVersion" method. */ public static final int GET_PROTOCOL_VERSION_METHOD_NUMBER = 8; /** * The name of the method used to retrieve the HTTP status code for this * response. */ public static final String GET_STATUS_CODE_METHOD_NAME = "getstatuscode"; /** * The method number for the "getStatusCode" method. */ public static final int GET_STATUS_CODE_METHOD_NUMBER = 9; /** * The name of the method used to determine whether this is a null response. */ public static final String IS_NULL_METHOD_NAME = "isnull"; /** * The method number for the "isNull" method. */ public static final int IS_NULL_METHOD_NUMBER = 10; /** * The set of methods associated with HTML document variables. */ public static final Method[] HTTP_RESPONSE_VARIABLE_METHODS = new Method[] { new Method(GET_CONTENT_LENGTH_METHOD_NAME, new String[0], IntegerVariable.INTEGER_VARIABLE_TYPE), new Method(GET_CONTENT_TYPE_METHOD_NAME, new String[0], StringVariable.STRING_VARIABLE_TYPE), new Method(GET_DATA_AS_STRING_METHOD_NAME, new String[0], StringVariable.STRING_VARIABLE_TYPE), new Method(GET_HEADER_METHOD_NAME, new String[] { StringVariable.STRING_VARIABLE_TYPE }, StringVariable.STRING_VARIABLE_TYPE), new Method(GET_HEADER_NAMES_METHOD_NAME, new String[0], StringArrayVariable.STRING_ARRAY_VARIABLE_TYPE), new Method(GET_HEADER_VALUES_METHOD_NAME, new String[] { StringVariable.STRING_VARIABLE_TYPE }, StringArrayVariable.STRING_ARRAY_VARIABLE_TYPE), new Method(GET_HTML_DOCUMENT_METHOD_NAME, new String[0], HTMLDocumentVariable.HTML_DOCUMENT_VARIABLE_TYPE), new Method(GET_RESPONSE_MESSAGE_METHOD_NAME, new String[0], StringVariable.STRING_VARIABLE_TYPE), new Method(GET_PROTOCOL_VERSION_METHOD_NAME, new String[0], StringVariable.STRING_VARIABLE_TYPE), new Method(GET_STATUS_CODE_METHOD_NAME, new String[0], IntegerVariable.INTEGER_VARIABLE_TYPE), new Method(IS_NULL_METHOD_NAME, new String[0], BooleanVariable.BOOLEAN_VARIABLE_TYPE) }; // The actual HTTP response used to perform all processing. private HTTPResponse httpResponse; /** * Creates a new 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 HTTPResponseVariable() throws ScriptException { httpResponse = null; } /** * Creates a new HTTP response variable based on the provided response. * * @param httpResponse The HTTP response to use to initialize this variable. */ public HTTPResponseVariable(HTTPResponse httpResponse) { this.httpResponse = httpResponse; } /** * Retrieves the name of the variable type for this variable. * * @return The name of the variable type for this variable. */ @Override() public String getVariableTypeName() { return HTTP_RESPONSE_VARIABLE_TYPE; } /** * Retrieves a list of all methods defined for this variable. * * @return A list of all methods defined for this variable. */ @Override() public Method[] getMethods() { return HTTP_RESPONSE_VARIABLE_METHODS; } /** * Indicates whether this variable type has a method with the specified name. * * @param methodName The name of the method. * * @return <CODE>true</CODE> if this variable has a method with the specified * name, or <CODE>false</CODE> if it does not. */ @Override() public boolean hasMethod(String methodName) { for (int i=0; i < HTTP_RESPONSE_VARIABLE_METHODS.length; i++) { if (HTTP_RESPONSE_VARIABLE_METHODS[i].getName().equals(methodName)) { return true; } } return false; } /** * Retrieves the method number for the method that has the specified name and * argument types, or -1 if there is no such method. * * @param methodName The name of the method. * @param argumentTypes The list of argument types for the method. * * @return The method number for the method that has the specified name and * argument types. */ @Override() public int getMethodNumber(String methodName, String[] argumentTypes) { for (int i=0; i < HTTP_RESPONSE_VARIABLE_METHODS.length; i++) { if (HTTP_RESPONSE_VARIABLE_METHODS[i].hasSignature(methodName, argumentTypes)) { return i; } } return -1; } /** * Retrieves the return type for the method with the specified name and * argument types. * * @param methodName The name of the method. * @param argumentTypes The set of argument types for the method. * * @return The return type for the method, or <CODE>null</CODE> if there is * no such method defined. */ @Override() public String getReturnTypeForMethod(String methodName, String[] argumentTypes) { for (int i=0; i < HTTP_RESPONSE_VARIABLE_METHODS.length; i++) { if (HTTP_RESPONSE_VARIABLE_METHODS[i].hasSignature(methodName, argumentTypes)) { return HTTP_RESPONSE_VARIABLE_METHODS[i].getReturnType(); } } 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 of the script in which the method * call occurs. * @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 <CODE>null</CODE> if it * does not return a value. * * @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 { switch (methodNumber) { case GET_CONTENT_LENGTH_METHOD_NUMBER: if (httpResponse == null) { return new IntegerVariable(-1); } else { return new IntegerVariable(httpResponse.getContentLength()); } case GET_CONTENT_TYPE_METHOD_NUMBER: if (httpResponse == null) { return new StringVariable(); } else { return new StringVariable(httpResponse.getContentType()); } case GET_DATA_AS_STRING_METHOD_NUMBER: if (httpResponse == null) { return new StringVariable(); } else { byte[] responseData = httpResponse.getResponseData(); if ((responseData == null) || (responseData.length == 0)) { return new StringVariable(); } else { return new StringVariable(new String(responseData)); } } case GET_HEADER_METHOD_NUMBER: StringVariable sv = (StringVariable) arguments[0].getArgumentValue(); if (httpResponse == null) { return new StringVariable(); } else { return new StringVariable(httpResponse.getHeader(sv.getStringValue())); } case GET_HEADER_NAMES_METHOD_NUMBER: if (httpResponse == null) { return new StringArrayVariable(); } else { String[][] headerElements = httpResponse.getHeaderElements(); ArrayList<String> nameList = new ArrayList<String>(); for (int i=0; i < headerElements.length; i++) { if (! nameList.contains(headerElements[0])) { nameList.add(headerElements[i][0]); } } String[] headerNames = new String[nameList.size()]; nameList.toArray(headerNames); return new StringArrayVariable(headerNames); } case GET_HEADER_VALUES_METHOD_NUMBER: sv = (StringVariable) arguments[0].getArgumentValue(); if (httpResponse == null) { return new StringArrayVariable(); } else { return new StringArrayVariable( httpResponse.getHeaderValues(sv.getStringValue())); } case GET_HTML_DOCUMENT_METHOD_NUMBER: if (httpResponse == null) { return new HTMLDocumentVariable(); } else { return new HTMLDocumentVariable(httpResponse.getHTMLDocument()); } case GET_RESPONSE_MESSAGE_METHOD_NUMBER: if (httpResponse == null) { return new StringVariable(); } else { return new StringVariable(httpResponse.getResponseMessage()); } case GET_PROTOCOL_VERSION_METHOD_NUMBER: if (httpResponse == null) { return new StringVariable(); } else { return new StringVariable(httpResponse.getProtocolVersion()); } case GET_STATUS_CODE_METHOD_NUMBER: if (httpResponse == null) { return new IntegerVariable(-1); } else { return new IntegerVariable(httpResponse.getStatusCode()); } case IS_NULL_METHOD_NUMBER: return new BooleanVariable(httpResponse == null); default: throw new ScriptException(lineNumber, "There is no method " + methodNumber + " defined for " + getArgumentType() + " variables."); } } /** * Assigns the value of the provided argument to this variable. The value of * the provided argument must be of the same type as this variable. * * @param argument The argument whose value should be assigned to this * variable. * * @throws ScriptException If a problem occurs while performing the * assignment. */ @Override() public void assign(Argument argument) throws ScriptException { if (! argument.getArgumentType().equals(HTTP_RESPONSE_VARIABLE_TYPE)) { throw new ScriptException("Attempt to assign an argument of type " + argument.getArgumentType() + " to a variable of type " + HTTP_RESPONSE_VARIABLE_TYPE + " rejected."); } HTTPResponseVariable hrv = (HTTPResponseVariable) argument.getArgumentValue(); httpResponse = hrv.httpResponse; } /** * Retrieves a string representation of the value of this argument. * * @return A string representation of the value of this argument. */ public String getValueAsString() { if (httpResponse == null) { return "null"; } else { return httpResponse.getProtocolVersion() + ' ' + httpResponse.getStatusCode() + ' ' + httpResponse.getResponseMessage(); } } }