/* * 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.http; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.net.URL; import java.util.ArrayList; import java.util.zip.GZIPInputStream; /** * This class defines a means of encapsulating an HTTP response returned by a * server in response to an HTTP request. * * * @author Neil A. Wilson */ public class HTTPResponse { // The set of cookie values included in this response. private ArrayList<String> cookieValueList; // The names of the headers included in this response. private ArrayList<String> headerNameList; // The values of the headers included in this response. private ArrayList<String> headerValueList; // The actual data associated with this response. private byte[] responseData; // The HTML document included in the response, if appropriate. private HTMLDocument htmlDocument; // The number of bytes contained in the content of the response. private int contentLength; // The HTTP status code for the response. private int statusCode; // The MIME type of the response. private String contentType; // The protocol version string for this response. private String protolVersion; // The response message for this response. private String responseMessage; // The URL of the request that generated this response. private URL requestURL; /** * Creates a new HTTP response with the provided status code. * * @param requestURL The URL of the request that generated this * response. * @param statusCode The HTTP status code for this response. * @param protocolVersion The protocol and version for this response. * @param responseMessage The message associated with this response. */ public HTTPResponse(URL requestURL, int statusCode, String protocolVersion, String responseMessage) { this.requestURL = requestURL; this.statusCode = statusCode; this.protolVersion = protocolVersion; this.responseMessage = responseMessage; htmlDocument = null; contentType = null; contentLength = -1; responseData = new byte[0]; cookieValueList = new ArrayList<String>(); headerNameList = new ArrayList<String>(); headerValueList = new ArrayList<String>(); } /** * Retrieves the URL of the request that generated this HTTP response. * * @return The URL of the request that generated this HTTP response. */ public URL getRequestURL() { return requestURL; } /** * Retrieves the status code for this HTTP response. * * @return The status code for this HTTP response. */ public int getStatusCode() { return statusCode; } /** * Retrieves the protocol version for this HTTP response. * * @return The protocol version for this HTTP response. */ public String getProtocolVersion() { return protolVersion; } /** * Retrieves the response message for this HTTP response. * * @return The response message for this HTTP response. */ public String getResponseMessage() { return responseMessage; } /** * Retrieves the value of the header with the specified name. If the * specified header has more than one value, then only the first will be * retrieved. * * @param headerName The name of the header to retrieve. * * @return The value of the header with the specified name, or * <CODE>null</CODE> if no such header is available. */ public String getHeader(String headerName) { String lowerName = headerName.toLowerCase(); for (int i=0; i < headerNameList.size(); i++) { if (lowerName.equals(headerNameList.get(i))) { return headerValueList.get(i); } } return null; } /** * Retrieves the set of values for the specified header. * * @param headerName The name of the header to retrieve. * * @return The set of values for the specified header. */ public String[] getHeaderValues(String headerName) { ArrayList<String> valueList = new ArrayList<String>(); String lowerName = headerName.toLowerCase(); for (int i=0; i < headerNameList.size(); i++) { if (lowerName.equals(headerNameList.get(i))) { valueList.add(headerValueList.get(i)); } } String[] values = new String[valueList.size()]; valueList.toArray(values); return values; } /** * Adds a header with the given name and value to this response. * * @param headerName The name of the header to add to this response. * @param headerValue The value of the header to add to this response. */ public void addHeader(String headerName, String headerValue) { String lowerName = headerName.toLowerCase(); headerNameList.add(lowerName); headerValueList.add(headerValue); if (lowerName.equals("content-length")) { try { contentLength = Integer.parseInt(headerValue); } catch (NumberFormatException nfe) {} } else if (lowerName.equals("content-type")) { contentType = headerValue; } else if (lowerName.equals("set-cookie")) { cookieValueList.add(headerValue); } } /** * Retrieves a two-dimensional array containing the header data for this * response, with each element being an array containing a name/value pair. * * @return A two-dimensional array containing the header data for this * response. */ public String[][] getHeaderElements() { String[][] headerElements = new String[headerNameList.size()][2]; for (int i=0; i < headerNameList.size(); i++) { headerElements[i][0] = headerNameList.get(i); headerElements[i][1] = headerValueList.get(i); } return headerElements; } /** * Retrieves the raw data included in this HTTP response. If the response did * not include any data, an empty array will be returned. * * @return The raw data included in this HTTP response. */ public byte[] getResponseData() { return responseData; } /** * Sets the actual data associated with this response. * * @param responseData The actual data associated with this response. * * @throws IOException If the data is GZIP-compressed and a problem occurs * during decompression. */ public void setResponseData(byte[] responseData) throws IOException { if (responseData == null) { this.responseData = new byte[0]; } else { // If the response is compressed, then decompress it. String contentEncoding = getHeader("content-encoding"); if (contentEncoding != null) { contentEncoding = contentEncoding.toLowerCase(); if (contentEncoding.contains("gzip")) { ByteArrayInputStream bais = new ByteArrayInputStream(responseData); GZIPInputStream gzis = new GZIPInputStream(bais); ByteArrayOutputStream baos = new ByteArrayOutputStream(responseData.length); byte[] buffer = new byte[8192]; int bytesRead = gzis.read(buffer); while (bytesRead > 0) { baos.write(buffer, 0, bytesRead); bytesRead = gzis.read(buffer); } responseData = baos.toByteArray(); } } this.responseData = responseData; } } /** * Retrieves the content length associated with this response. * * @return The content length associated with this response, or -1 if no * content length is available. */ public int getContentLength() { return contentLength; } /** * Retrieves the content type associated with this response. * * @return The content type associated with this response, or * <CODE>null</CODE> if no content type is available. */ public String getContentType() { return contentType; } /** * Retrieves an array containing the values of the cookies that should be set * based on the information in this response. * * @return An array containing the values of the cookies that should be set * based on the information in this response. */ public String[] getCookieValues() { String[] cookieValues = new String[cookieValueList.size()]; cookieValueList.toArray(cookieValues); return cookieValues; } /** * Retrieves the HTML document associated with this response. * * @return The HTML document associated with this response, or * <CODE>null</CODE> if no HTML document is available. */ public HTMLDocument getHTMLDocument() { if ((htmlDocument == null) && (contentType != null) && (contentType.toLowerCase().contains("text/html"))) { parseAsHTMLDocument(requestURL); } return htmlDocument; } /** * Parses the data associated with this response as an HTML document. * * @param requestURL The URL of the request that triggered this response. */ public void parseAsHTMLDocument(URL requestURL) { try { String htmlString = new String(responseData); htmlDocument = new HTMLDocument(requestURL.toExternalForm(), htmlString); } catch (Exception e) { e.printStackTrace(); } } }