/*
 * Copyright 2001-2004 The Apache Software Foundation.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.jmeter.protocol.http.sampler;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.net.URL;

import java.util.Date;
import java.util.Map;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Vector;
import java.util.Enumeration;

import org.apache.commons.httpclient.ConnectMethod;
import org.apache.commons.httpclient.DefaultMethodRetryHandler;
import org.apache.commons.httpclient.HostConfiguration;
import org.apache.commons.httpclient.HttpConnection;
import org.apache.commons.httpclient.HttpMethod;
import org.apache.commons.httpclient.HttpMethodBase;
import org.apache.commons.httpclient.HttpState;
import org.apache.commons.httpclient.NTCredentials;
import org.apache.commons.httpclient.methods.EntityEnclosingMethod;
import org.apache.commons.httpclient.methods.GetMethod;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.protocol.Protocol;
import org.apache.jmeter.config.Argument;

import org.apache.jmeter.protocol.http.control.AuthManager;
import org.apache.jmeter.protocol.http.control.Authorization;
import org.apache.jmeter.protocol.http.control.CookieManager;
import org.apache.jmeter.protocol.http.control.HeaderManager;
import org.apache.jmeter.protocol.http.control.Cookie;
import org.apache.jmeter.protocol.http.control.Header;

import org.apache.jmeter.testelement.property.CollectionProperty;
import org.apache.jmeter.testelement.property.PropertyIterator;
import org.apache.jmeter.util.JMeterUtils;

import org.apache.jorphan.logging.LoggingManager;

import org.apache.log.Logger;

/**
 * A sampler which understands all the parts necessary to read statistics about
 * HTTP requests, including cookies and authentication.
 * 
 */
public class HTTPSampler2 extends HTTPSamplerBase {
	transient private static Logger log = LoggingManager.getLoggerForClass();
	transient private static ThreadLocal httpClients = null;

	static {
		// Set the default to Avalon Logkit, if not already defined:
		if (System.getProperty("org.apache.commons.logging.Log") == null) {
			System.setProperty("org.apache.commons.logging.Log", "org.apache.commons.logging.impl.LogKitLogger");
		}
	}

	/*
	 * Connection is re-used if possible
	 */
	//private transient HttpConnection httpConn = null;

	/*
	 * These variables are recreated every time Find a better way of passing
	 * them round
	 */
	private transient HttpMethodBase httpMethod = null;

	private transient HttpState httpState = null;

	private static boolean basicAuth = JMeterUtils.getPropDefault("httpsampler2.basicauth", false);

	static {
		log.info("httpsampler2.basicauth=" + basicAuth);
	}

	/**
	 * Constructor for the HTTPSampler2 object.
	 */
	public HTTPSampler2() {
	}

	/**
	 * Set request headers in preparation to opening a connection.
	 * 
	 * @param conn
	 *            <code>URLConnection</code> to set headers on
	 * @exception IOException
	 *                if an I/O exception occurs
	 */
	private void setPostHeaders(PostMethod post) throws IOException {
		// Probably nothing needed, because the PostMethod class takes care of
		// it
		// /*postWriter.*/
		// setHeaders(post, this);
	}

	/**
	 * Send POST data from <code>Entry</code> to the open connection.
	 * 
	 * @param connection
	 *            <code>URLConnection</code> where POST data should be sent
	 * @exception IOException
	 *                if an I/O exception occurs
	 */
	private void sendPostData(HttpMethod connection) throws IOException {
		/* postWriter. */
		sendPostData((PostMethod) connection, this);
	}

	/**
	 * Send POST data from Entry to the open connection.
	 */
	public void sendPostData(PostMethod post, HTTPSampler2 sampler) throws IOException {
		PropertyIterator args = sampler.getArguments().iterator();
		while (args.hasNext()) {
			Argument arg = (Argument) args.next().getObjectValue();
			post.addParameter(arg.getName(), arg.getValue());
		}
		// If filename was specified then send the post using multipart syntax
		String filename = sampler.getFilename();
		if ((filename != null) && (filename.trim().length() > 0)) {
			File input = new File(filename);
			if (input.length() < Integer.MAX_VALUE) {
				post.setRequestContentLength((int) input.length());
			} else {
				post.setRequestContentLength(EntityEnclosingMethod.CONTENT_LENGTH_CHUNKED);
			}
			// TODO - is this correct?
			post.setRequestHeader("Content-Disposition", "form-data; name=\"" + encode(sampler.getFileField())
					+ "\"; filename=\"" + encode(filename) + "\"");
			// Specify content type and encoding
			post.setRequestHeader("Content-Type", sampler.getMimetype());
			post.setRequestBody(new FileInputStream(input));
		}
	}

	private String encode(String value) {
		StringBuffer newValue = new StringBuffer();
		char[] chars = value.toCharArray();
		for (int i = 0; i < chars.length; i++) {
			if (chars[i] == '\\') {
				newValue.append("\\\\");
			} else {
				newValue.append(chars[i]);
			}
		}
		return newValue.toString();
	}

	/**
	 * Returns an <code>HttpConnection</code> fully ready to attempt
	 * connection. This means it sets the request method (GET or POST), headers,
	 * cookies, and authorization for the URL request.
	 * <p>
	 * The request infos are saved into the sample result if one is provided.
	 * 
	 * @param u
	 *            <code>URL</code> of the URL request
	 * @param method
	 *            http/https
	 * @param res
	 *            sample result to save request infos to
	 * @return <code>HttpConnection</code> ready for .connect
	 * @exception IOException
	 *                if an I/O Exception occurs
	 */
	private HttpConnection setupConnection(URL u, String method, HTTPSampleResult res) throws IOException {

		String urlStr = u.toString();

		org.apache.commons.httpclient.URI uri = new org.apache.commons.httpclient.URI(urlStr);

		String schema = uri.getScheme();
		if ((schema == null) || (schema.equals(""))) {
			schema = "http";
		}
		Protocol protocol = Protocol.getProtocol(schema);

		String host = uri.getHost();
		int port = uri.getPort();

		HostConfiguration hc = new HostConfiguration();
		hc.setHost(host, port, protocol);

		HttpConnection httpConn = null;
		Map map = (Map)httpClients.get();
		synchronized ( map )
		{
			httpConn = (HttpConnection)map.get(hc);
			
			if ( httpConn == null )
			{
				httpConn = new HttpConnection(hc);
				// TODO check these
				httpConn.setProxyHost(System.getProperty("http.proxyHost"));
				httpConn.setProxyPort(Integer.parseInt(System.getProperty("http.proxyPort", "80")));
				
				map.put(hc, httpConn);
			}
		}

		/*if (httpConn != null && hc.hostEquals(httpConn)) {
			// Same details, no need to reset
		} else {
			httpConn = new HttpConnection(hc);
			// TODO check these
			httpConn.setProxyHost(System.getProperty("http.proxyHost"));
			httpConn.setProxyPort(Integer.parseInt(System.getProperty("http.proxyPort", "80")));
		}*/

		if (method.equals(POST)) {
			httpMethod = new PostMethod(urlStr);
		} else {
			httpMethod = new GetMethod(urlStr);
			// httpMethod;
			new DefaultMethodRetryHandler();
		}

		httpMethod.setHttp11(!JMeterUtils.getPropDefault("httpclient.version", "1.1").equals("1.0"));

		// Set the timeout (if non-zero)
		httpConn.setSoTimeout(JMeterUtils.getPropDefault("httpclient.timeout", 0));

		httpState = new HttpState();
		if (httpConn.isProxied() && httpConn.isSecure()) {
			httpMethod = new ConnectMethod(httpMethod);
		}

		// Allow HttpClient to handle the redirects:
		httpMethod.setFollowRedirects(getPropertyAsBoolean(AUTO_REDIRECTS));

		// a well-behaved browser is supposed to send 'Connection: close'
		// with the last request to an HTTP server. Instead, most browsers
		// leave it to the server to close the connection after their
		// timeout period. Leave it to the JMeter user to decide.
		if (getUseKeepAlive()) {
			httpMethod.addRequestHeader("Connection", "keep-alive");
		} else {
			httpMethod.addRequestHeader("Connection", "close");
		}

		String hdrs = setConnectionHeaders(httpMethod, u, getHeaderManager());
		String cookies = setConnectionCookie(httpMethod, u, getCookieManager());
		//System.out.println("setupConnection: cookies = " + cookies);

		if (res != null) {
			StringBuffer sb = new StringBuffer();
			if (method.equals(POST)) {
				String q = this.getQueryString();
				res.setQueryString(q);
				sb.append("Query data:\n");
				sb.append(q);
				sb.append('\n');
			}
			if (cookies != null) {
				res.setCookies(cookies);
				sb.append("\nCookie Data:\n");
				sb.append(cookies);
				sb.append('\n');
			}
			res.setSamplerData(sb.toString());
			// TODO rather than stuff all the information in here,
			// pick it up from the individual fields later

			res.setURL(u);
			res.setHTTPMethod(method);
			res.setRequestHeaders(hdrs);
			res.setQueryString(getQueryString());
		}

		setConnectionAuthorization(httpMethod, u, getAuthManager());

		if (method.equals(POST)) {
			setPostHeaders((PostMethod) httpMethod);
		}

		//System.out.println("Dumping Request Headers:");
		//System.out.println(method.getRequestHeaders().toString());
		/*Header[] headers = method.getRequestHeaders();
		for (int i = 0; i < headers.length; i++)
		{
			System.out.println("Header["+i+"]:");
			org.apache.commons.httpclient.HeaderElement[] elements = headers[i].getElements();
			
			for (j=0; j<elements.length; j++)
			{
				System.out.println("Element["+j+"]:");
				org.apache.commons.httpclient.NameValuePair[] pairs = elements[j].getParameters();
				
				for (k=0; k<pairs.length;k++)
				{
					System.out.println("pair["+k+"]: " + pairs[k].getName() + "=" + pairs[k].getValue());
				}
			}
		}*/

		return httpConn;
	}
	
	/**
	 * Gets the ResponseHeaders
	 * 
	 * @param method
	 *            connection from which the headers are read
	 * @return string containing the headers, one per line
	 */
	protected String getResponseHeaders(HttpMethod method) throws IOException {
		StringBuffer headerBuf = new StringBuffer();
		org.apache.commons.httpclient.Header rh[] = method.getResponseHeaders();
		headerBuf.append(method.getStatusLine());// header[0] is not the
													// status line...
		headerBuf.append("\n");

		for (int i = 0; i < rh.length; i++) {
			String key = rh[i].getName();
			if (!key.equalsIgnoreCase("transfer-encoding"))// TODO - why is
															// this not saved?
			{
				headerBuf.append(key);
				headerBuf.append(": ");
				headerBuf.append(rh[i].getValue());
				headerBuf.append("\n");
			}
		}
		return headerBuf.toString();
	}

	/**
	 * Extracts all the required cookies for that particular URL request and
	 * sets them in the <code>HttpMethod</code> passed in.
	 * 
	 * @param method
	 *            <code>HttpMethod</code> which represents the request
	 * @param u
	 *            <code>URL</code> of the request
	 * @param cookieManager
	 *            the <code>CookieManager</code> containing all the cookies
	 *            for this <code>UrlConfig</code>
	 */
	private String setConnectionCookie(HttpMethod method, URL u, CookieManager cookieManager) {
		String cookieHeader = "";
		String host = "." + u.getHost();
		
		for (int i = cookieManager.getCookies().size() - 1; i >= 0; i--) {
			Cookie cookie = (Cookie) cookieManager.getCookies().get(i).getObjectValue();
			if (cookie == null)
				continue;
			if ( host.endsWith(cookie.getDomain()) && u.getFile().startsWith(cookie.getPath()) && (cookie.getExpires() == 0)) {
				org.apache.commons.httpclient.Cookie newCookie = new org.apache.commons.httpclient.Cookie(cookie.getDomain(), cookie.getName(),
				     cookie.getValue(), cookie.getPath(), null, false);
				httpState.addCookie(newCookie);
				cookieHeader += cookie.getName() + "=" + cookie.getValue();
			}
		}

		/*String cookieHeader = null;
		if (cookieManager != null) {
			cookieHeader = cookieManager.getCookieHeaderForURL(u);
			//System.out.println("Cookie: " + cookieHeader);
			if (cookieHeader != null) {
				method.addRequestHeader("Cookie", cookieHeader);
			}
		}*/
		return cookieHeader;
	}

	/**
	 * Extracts all the required headers for that particular URL request and
	 * sets them in the <code>HttpMethod</code> passed in
	 * 
	 * @param method
	 *            <code>HttpMethod</code> which represents the request
	 * @param u
	 *            <code>URL</code> of the URL request
	 * @param headerManager
	 *            the <code>HeaderManager</code> containing all the cookies
	 *            for this <code>UrlConfig</code>
	 * @return the headers as a string
	 */
	private String setConnectionHeaders(HttpMethod method, URL u, HeaderManager headerManager) {
		StringBuffer hdrs = new StringBuffer(100);
		if (headerManager != null) {
			CollectionProperty headers = headerManager.getHeaders();
			if (headers != null) {
				PropertyIterator i = headers.iterator();
				while (i.hasNext()) {
					org.apache.jmeter.protocol.http.control.Header header = (org.apache.jmeter.protocol.http.control.Header) i
							.next().getObjectValue();
					String n = header.getName();
					String v = header.getValue();
					method.addRequestHeader(n, v);
					hdrs.append(n);
					hdrs.append(": ");
					hdrs.append(v);
					hdrs.append("\n");
				}
			}
		}
		return hdrs.toString();
	}

	/**
	 * Extracts all the required authorization for that particular URL request
	 * and sets it in the <code>HttpMethod</code> passed in.
	 * 
	 * @param method
	 *            <code>HttpMethod</code> which represents the request
	 * @param u
	 *            <code>URL</code> of the URL request
	 * @param authManager
	 *            the <code>AuthManager</code> containing all the cookies for
	 *            this <code>UrlConfig</code>
	 */
	private void setConnectionAuthorization(HttpMethod method, URL u, AuthManager authManager) {
		if (authManager != null) {
			if (basicAuth) {
				String authHeader = authManager.getAuthHeaderForURL(u);
				if (authHeader != null) {
					method.addRequestHeader("Authorization", authHeader);
				}
			} else {
				Authorization auth = authManager.getAuthForURL(u);
				if (auth != null) {
					// TODO - set up realm, thishost and domain
					httpState.setCredentials(null, // "realm"
							auth.getURL(), new NTCredentials(// Includes
																// other types
																// of
																// Credentials
									auth.getUser(), auth.getPass(), null, // "thishost",
									null // "targetdomain"
							));
				}
			}
		}
	}

	/**
	 * Samples the URL passed in and stores the result in
	 * <code>HTTPSampleResult</code>, following redirects and downloading
	 * page resources as appropriate.
	 * <p>
	 * When getting a redirect target, redirects are not followed and resources
	 * are not downloaded. The caller will take care of this.
	 * 
	 * @param url
	 *            URL to sample
	 * @param method
	 *            HTTP method: GET, POST,...
	 * @param areFollowingRedirect
	 *            whether we're getting a redirect target
	 * @param frameDepth
	 *            Depth of this target in the frame structure. Used only to
	 *            prevent infinite recursion.
	 * @return results of the sampling
	 */
	protected HTTPSampleResult sample(URL url, String method, boolean areFollowingRedirect, int frameDepth) {

		String urlStr = url.toString();

		log.debug("Start : sample" + urlStr);
		log.debug("method" + method);

		httpMethod = null;

		HTTPSampleResult res = new HTTPSampleResult();
		if (this.getPropertyAsBoolean(MONITOR)) {
			res.setMonitor(true);
		} else {
			res.setMonitor(false);
		}
		res.setSampleLabel(urlStr);
		res.sampleStart(); // Count the retries as well in the time

		try {
			HttpConnection connection = setupConnection(url, method, res);

			if (method.equals(POST)) {
				sendPostData(httpMethod);
			}

			int statusCode = httpMethod.execute(httpState, connection);

			// Request sent. Now get the response:
			byte[] responseData = httpMethod.getResponseBody();

			res.sampleEnd();
			// Done with the sampling proper.

			// Now collect the results into the HTTPSampleResult:

			res.setSampleLabel(httpMethod.getURI().toString());// Pick up
																// Actual path
																// (after
																// redirects)
			res.setResponseData(responseData);

			res.setResponseCode(Integer.toString(statusCode));
			res.setSuccessful(200 <= statusCode && statusCode <= 399);

			res.setResponseMessage(httpMethod.getStatusText());

			String ct = null;
			org.apache.commons.httpclient.Header h = httpMethod.getResponseHeader("Content-Type");
			if (h != null)// Can be missing, e.g. on redirect
			{
				ct = h.getValue();
				res.setContentType(ct);// e.g. text/html; charset=ISO-8859-1
			}
			if (ct != null) {
				// Extract charset and store as DataEncoding
				// TODO do we need process http-equiv META tags, e.g.:
				// <META http-equiv="content-type" content="text/html;
				// charset=foobar">
				// or can we leave that to the renderer ?
				String de = ct.toLowerCase();
				final String cs = "charset=";
				int cset = de.indexOf(cs);
				if (cset >= 0) {
					res.setDataEncoding(de.substring(cset + cs.length()));
				}
				if (ct.startsWith("image/")) {
					res.setDataType(HTTPSampleResult.BINARY);
				} else {
					res.setDataType(HTTPSampleResult.TEXT);
				}
			}

			res.setResponseHeaders(getResponseHeaders(httpMethod));
			if (res.isRedirect()) {
				res.setRedirectLocation(httpMethod.getResponseHeader("Location").getValue());
			}

			// Store any cookies received in the cookie manager:
			saveConnectionCookies(httpState, getCookieManager());

			// Follow redirects and download page resources if appropriate:
			res = resultProcessing(areFollowingRedirect, frameDepth, res);

			log.debug("End : sample");
			if (httpMethod != null)
				httpMethod.releaseConnection();
			return res;
		} catch (IllegalArgumentException e)// e.g. some kinds of invalid URL
		{
			res.sampleEnd();
			HTTPSampleResult err = errorResult(e, res);
			err.setSampleLabel("Error: " + url.toString());
			return err;
		} catch (IOException e) {
			res.sampleEnd();
			HTTPSampleResult err = errorResult(e, res);
			err.setSampleLabel("Error: " + url.toString());
			return err;
		} finally {
			if (httpMethod != null)
				httpMethod.releaseConnection();
		}
	}

	/**
	 * From the <code>HttpState</code>, store all the "set-cookie" key-pair
	 * values in the cookieManager of the <code>UrlConfig</code>.
	 * 
	 * @param state
	 *            <code>HttpState</code> which represents the request
	 * @param u
	 *            <code>URL</code> of the URL request
	 * @param cookieManager
	 *            the <code>CookieManager</code> containing all the cookies
	 *            for this <code>UrlConfig</code>
	 */
	private void saveConnectionCookies(HttpState state, CookieManager cookieManager) {
		if (cookieManager != null) {
			org.apache.commons.httpclient.Cookie [] c = state.getCookies();
			for (int i = 0; i < c.length; i++) {
				Date exp = c[i].getExpiryDate();// might be absent
				//System.out.println("Cookie[" + i + "]: " + c[i].getName() + " := " + c[i].getValue());

				Cookie cookie = new Cookie(c[i].getName(), 
					c[i].getValue(), c[i].getDomain(), c[i].getPath(), c[i].getSecure(), exp == null ? 0 : exp.getTime() / 1000);
				
				removeExistingCookie( cookie, cookieManager);
				
				cookieManager.add( cookie );
			}
		}
	}
	
	private void removeExistingCookie( Cookie newCookie, CookieManager cookieManager )
	{
		Vector removeIndices = new Vector();
		for (int i = cookieManager.getCookies().size() - 1; i >= 0; i--) {
			Cookie cookie = (Cookie) cookieManager.getCookies().get(i).getObjectValue();
			if (cookie == null)
				continue;
			if (cookie.getPath().equals(newCookie.getPath()) && cookie.getDomain().equals(newCookie.getDomain())
					&& cookie.getName().equals(newCookie.getName())) {
				if (log.isDebugEnabled()) {
					//System.out.println("New Cookie = " + newCookie.toString() + " removing matching Cookie "
									//+ cookie.toString());
				}
				removeIndices.addElement(new Integer(i));
			}
		}

		int index = 0;
		for (Enumeration e = removeIndices.elements(); e.hasMoreElements();) {
			index = ((Integer) e.nextElement()).intValue();
			cookieManager.remove(index);
		}
	}

	public void threadStarted() {
		log.debug("Thread Started");
		
		System.setProperty("apache.commons.httpclient.cookiespec", "COMPATIBILITY");
		
		synchronized ( this.getClass() )
		{
			if ( httpClients == null ) {
				httpClients = new ThreadLocal();
			}
			httpClients.set ( new HashMap() );
		}
	}

	public void threadFinished() {
		log.debug("Thread Finished");
		//if (httpConn != null)
		//	httpConn.close();
		
		synchronized ( this.getClass() )
		{
			Map map = (Map)httpClients.get();

			HttpConnection conn = null;
			if ( map != null ) {
				for ( Iterator it = map.entrySet().iterator(); it.hasNext(); )
				{
					Object obj = it.next();
					conn = (HttpConnection) ((Map.Entry)obj).getValue();
					conn.close();
				}
				map.clear();
			}
			
			httpClients.set( null );
		}
	}

	// ////////////////////////////////////////////////////////////////////////////////////////////////

	public static class Test extends junit.framework.TestCase {
		public Test(String name) {
			super(name);
		}

		public void testArgumentWithoutEquals() throws Exception {
			HTTPSampler2 sampler = new HTTPSampler2();
			sampler.setProtocol("http");
			sampler.setMethod(GET);
			sampler.setPath("/index.html?pear");
			sampler.setDomain("www.apache.org");
			assertEquals("http://www.apache.org/index.html?pear", sampler.getUrl().toString());
		}

		public void testMakingUrl() throws Exception {
			HTTPSampler2 config = new HTTPSampler2();
			config.setProtocol("http");
			config.setMethod(GET);
			config.addArgument("param1", "value1");
			config.setPath("/index.html");
			config.setDomain("www.apache.org");
			assertEquals("http://www.apache.org/index.html?param1=value1", config.getUrl().toString());
		}

		public void testMakingUrl2() throws Exception {
			HTTPSampler2 config = new HTTPSampler2();
			config.setProtocol("http");
			config.setMethod(GET);
			config.addArgument("param1", "value1");
			config.setPath("/index.html?p1=p2");
			config.setDomain("www.apache.org");
			assertEquals("http://www.apache.org/index.html?param1=value1&p1=p2", config.getUrl().toString());
		}

		public void testMakingUrl3() throws Exception {
			HTTPSampler2 config = new HTTPSampler2();
			config.setProtocol("http");
			config.setMethod(POST);
			config.addArgument("param1", "value1");
			config.setPath("/index.html?p1=p2");
			config.setDomain("www.apache.org");
			assertEquals("http://www.apache.org/index.html?p1=p2", config.getUrl().toString());
		}

		// test cases for making Url, and exercise method
		// addArgument(String name,String value,String metadata)

		public void testMakingUrl4() throws Exception {
			HTTPSampler2 config = new HTTPSampler2();
			config.setProtocol("http");
			config.setMethod(GET);
			config.addArgument("param1", "value1", "=");
			config.setPath("/index.html");
			config.setDomain("www.apache.org");
			assertEquals("http://www.apache.org/index.html?param1=value1", config.getUrl().toString());
		}

		public void testMakingUrl5() throws Exception {
			HTTPSampler2 config = new HTTPSampler2();
			config.setProtocol("http");
			config.setMethod(GET);
			config.addArgument("param1", "", "=");
			config.setPath("/index.html");
			config.setDomain("www.apache.org");
			assertEquals("http://www.apache.org/index.html?param1=", config.getUrl().toString());
		}

		public void testMakingUrl6() throws Exception {
			HTTPSampler2 config = new HTTPSampler2();
			config.setProtocol("http");
			config.setMethod(GET);
			config.addArgument("param1", "", "");
			config.setPath("/index.html");
			config.setDomain("www.apache.org");
			assertEquals("http://www.apache.org/index.html?param1", config.getUrl().toString());
		}

		// test cases for making Url, and exercise method
		// parseArguments(String queryString)

		public void testMakingUrl7() throws Exception {
			HTTPSampler2 config = new HTTPSampler2();
			config.setProtocol("http");
			config.setMethod(GET);
			config.parseArguments("param1=value1");
			config.setPath("/index.html");
			config.setDomain("www.apache.org");
			assertEquals("http://www.apache.org/index.html?param1=value1", config.getUrl().toString());
		}

		public void testMakingUrl8() throws Exception {
			HTTPSampler2 config = new HTTPSampler2();
			config.setProtocol("http");
			config.setMethod(GET);
			config.parseArguments("param1=");
			config.setPath("/index.html");
			config.setDomain("www.apache.org");
			assertEquals("http://www.apache.org/index.html?param1=", config.getUrl().toString());
		}

		public void testMakingUrl9() throws Exception {
			HTTPSampler2 config = new HTTPSampler2();
			config.setProtocol("http");
			config.setMethod(GET);
			config.parseArguments("param1");
			config.setPath("/index.html");
			config.setDomain("www.apache.org");
			assertEquals("http://www.apache.org/index.html?param1", config.getUrl().toString());
		}

		public void testMakingUrl10() throws Exception {
			HTTPSampler2 config = new HTTPSampler2();
			config.setProtocol("http");
			config.setMethod(GET);
			config.parseArguments("");
			config.setPath("/index.html");
			config.setDomain("www.apache.org");
			assertEquals("http://www.apache.org/index.html", config.getUrl().toString());
		}
	}
}
