package org.simpleframework.http.validate.test; import java.io.InputStream; import java.util.concurrent.CountDownLatch; import java.util.concurrent.atomic.AtomicBoolean; import org.apache.commons.httpclient.Header; import org.apache.commons.httpclient.HttpClient; import org.apache.commons.httpclient.HttpMethod; import org.apache.commons.httpclient.methods.GetMethod; import org.apache.commons.httpclient.methods.HeadMethod; import org.apache.commons.httpclient.methods.PostMethod; import org.simpleframework.common.KeyMap; import org.simpleframework.common.buffer.ArrayBuffer; import org.simpleframework.common.buffer.Buffer; import org.simpleframework.http.StatusLine; class Client implements Runnable { private final AtomicBoolean hasExecuted; private final HttpClient client; private final CountDownLatch latch; private final Scenario scenario; private final Analyser handler; private final StringBuilder target; private final KeyMap<String> header; private final Buffer body; private final int id; public Client(CountDownLatch latch, Analyser handler, Scenario scenario, StringBuilder target, KeyMap<String> header, Buffer body, int id) throws Exception { this.hasExecuted = new AtomicBoolean(false); this.client = new HttpClient(); this.scenario = scenario; this.handler = handler; this.target = target; this.latch = latch; this.header = header; this.body = body; this.id = id; } public void run() { try { if(hasExecuted.get()) { throw new IllegalStateException("Client of id '" +id+ "' has already executed"); } execute(); } catch(Exception e) { e.printStackTrace(); } finally { hasExecuted.set(true); } } private void execute() throws Exception { Method type = scenario.method(); int requests = scenario.requests(); for(int i = 0; i < requests; i++) { HttpMethod method = getMethod(type); try { method.addRequestHeader(RoundTripTest.REQUEST_ID, String.format("id-%s-%s", id, i)); client.executeMethod(method); analyse(method); } catch(Throwable e) { e.printStackTrace(); }finally { method.releaseConnection(); } } latch.countDown(); } private HttpMethod getMethod(Method method) throws Exception { Protocol protocol = scenario.protocol(); if(method == Method.GET) { return getGetMethod(protocol); } if(method == Method.POST) { return getPostMethod(protocol); } if(method == Method.HEAD) { return getHeadMethod(protocol); } return getGetMethod(protocol); } private HttpMethod getHeadMethod(Protocol protocol) throws Exception { HeadMethod head = new HeadMethod(protocol.getTarget()); head.setPath(target.toString()); for(String name : header) { head.addRequestHeader(name, header.get(name)); } return head; } private HttpMethod getGetMethod(Protocol protocol) throws Exception { GetMethod get = new GetMethod(protocol.getTarget()); get.setPath(target.toString()); for(String name : header) { get.addRequestHeader(name, header.get(name)); } return get; } private HttpMethod getPostMethod(Protocol protocol) throws Exception { PostMethod post = new PostMethod(protocol.getTarget()); post.setPath(target.toString()); post.setUseExpectHeader(true); for(String name : header) { post.addRequestHeader(name, header.get(name)); } InputStream requestBody = body.open(); post.setRequestBody(requestBody); return post; } private void analyse(HttpMethod method) throws Exception { KeyMap<String> message = new KeyMap<String>(); StatusLine status = new ResponseStatus(); int code = method.getStatusCode(); String text = method.getStatusText(); Header[] reply = method.getResponseHeaders(); boolean debug = scenario.debug(); for(Header header : reply) { String name = header.getName(); String value = header.getValue(); message.put(name, value); } InputStream responseStream = method.getResponseBodyAsStream(); Buffer responseBody = new ArrayBuffer(1048576); byte[] chunk = new byte[1024]; int count = 0; if(responseStream != null) { while((count = responseStream.read(chunk)) != -1) { responseBody.append(chunk, 0, count); } } if(debug) { System.err.println(responseBody.encode()); } status.setCode(code); status.setDescription(text); status.setMajor(1); status.setMinor(1); handler.analyse(status, message, responseBody); } }