blob: 469aef0ef55360f29087ae4b7b6cbd54d2d9a5d0 [file] [log] [blame]
package com.xtremelabs.robolectric.tester.org.apache.http;
import org.apache.http.Header;
import org.apache.http.HttpException;
import org.apache.http.HttpHost;
import org.apache.http.HttpRequest;
import org.apache.http.HttpResponse;
import org.apache.http.client.RequestDirector;
import org.apache.http.protocol.HttpContext;
import javax.xml.ws.http.HTTPException;
import java.io.IOException;
import java.net.URI;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.StringTokenizer;
import java.util.regex.Pattern;
public class FakeHttpLayer {
List<HttpResponse> pendingHttpResponses = new ArrayList<HttpResponse>();
List<HttpRequestInfo> httpRequestInfos = new ArrayList<HttpRequestInfo>();
List<HttpEntityStub.ResponseRule> httpResponseRules = new ArrayList<HttpEntityStub.ResponseRule>();
HttpResponse defaultHttpResponse;
private HttpResponse defaultResponse;
public void addPendingHttpResponse(int statusCode, String responseBody) {
addPendingHttpResponse(new TestHttpResponse(statusCode, responseBody));
}
public void addPendingHttpResponseWithContentType(int statusCode, String responseBody, Header contentType) {
addPendingHttpResponse(new TestHttpResponse(statusCode, responseBody, contentType));
}
public void addPendingHttpResponse(HttpResponse httpResponse) {
pendingHttpResponses.add(httpResponse);
}
public void addHttpResponseRule(String method, String uri, HttpResponse response) {
addHttpResponseRule(new DefaultRequestMatcher(method, uri), response);
}
public void addHttpResponseRule(String uri, HttpResponse response) {
addHttpResponseRule(new UriRequestMatcher(uri), response);
}
public void addHttpResponseRule(String uri, String response) {
addHttpResponseRule(new UriRequestMatcher(uri), new TestHttpResponse(200, response));
}
public void addHttpResponseRule(RequestMatcher requestMatcher, HttpResponse response) {
addHttpResponseRule(new RequestMatcherResponseRule(requestMatcher, response));
}
public void addHttpResponseRule(HttpEntityStub.ResponseRule responseRule) {
httpResponseRules.add(responseRule);
}
public void setDefaultHttpResponse(HttpResponse defaultHttpResponse) {
this.defaultHttpResponse = defaultHttpResponse;
}
public void setDefaultHttpResponse(int statusCode, String responseBody) {
setDefaultHttpResponse(new TestHttpResponse(statusCode, responseBody));
}
private HttpResponse findResponse(HttpRequest httpRequest) throws HttpException, IOException {
if (!pendingHttpResponses.isEmpty()) {
return pendingHttpResponses.remove(0);
}
for (HttpEntityStub.ResponseRule httpResponseRule : httpResponseRules) {
if (httpResponseRule.matches(httpRequest)) {
return httpResponseRule.getResponse();
}
}
return defaultHttpResponse;
}
public HttpResponse emulateRequest(HttpHost httpHost, HttpRequest httpRequest, HttpContext httpContext, RequestDirector requestDirector) throws HttpException, IOException {
HttpResponse httpResponse = findResponse(httpRequest);
if (httpResponse == null) {
throw new RuntimeException("Unexpected call to execute, no pending responses are available. See Robolectric.addPendingResponse().");
}
httpRequestInfos.add(new HttpRequestInfo(httpRequest, httpHost, httpContext, requestDirector));
return httpResponse;
}
public boolean hasPendingResponses() {
return !pendingHttpResponses.isEmpty();
}
public boolean hasRequestInfos() {
return !httpRequestInfos.isEmpty();
}
public boolean hasResponseRules() {
return !httpResponseRules.isEmpty();
}
public HttpResponse getDefaultResponse() {
return defaultResponse;
}
public HttpRequestInfo getSentHttpRequestInfo(int index) {
return httpRequestInfos.get(index);
}
public List<HttpRequestInfo> getSentHttpRequestInfos() {
return new ArrayList<HttpRequestInfo>(httpRequestInfos);
}
public void clearHttpResponseRules() {
httpResponseRules.clear();
}
public static class RequestMatcherResponseRule implements HttpEntityStub.ResponseRule {
private RequestMatcher requestMatcher;
private HttpResponse responseToGive;
private IOException ioException;
private HTTPException httpException;
public RequestMatcherResponseRule(RequestMatcher requestMatcher, HttpResponse responseToGive) {
this.requestMatcher = requestMatcher;
this.responseToGive = responseToGive;
}
public RequestMatcherResponseRule(RequestMatcher requestMatcher, IOException ioException) {
this.requestMatcher = requestMatcher;
this.ioException = ioException;
}
public RequestMatcherResponseRule(RequestMatcher requestMatcher, HTTPException httpException) {
this.requestMatcher = requestMatcher;
this.httpException = httpException;
}
@Override public boolean matches(HttpRequest request) {
return requestMatcher.matches(request);
}
@Override public HttpResponse getResponse() throws HttpException, IOException {
if (httpException != null) throw httpException;
if (ioException != null) throw ioException;
return responseToGive;
}
}
public static class DefaultRequestMatcher implements RequestMatcher {
private String method;
private String uri;
public DefaultRequestMatcher(String method, String uri) {
this.method = method;
this.uri = uri;
}
@Override public boolean matches(HttpRequest request) {
return request.getRequestLine().getMethod().equals(method) &&
request.getRequestLine().getUri().equals(uri);
}
}
public static class UriRequestMatcher implements RequestMatcher {
private String uri;
public UriRequestMatcher(String uri) {
this.uri = uri;
}
@Override public boolean matches(HttpRequest request) {
return request.getRequestLine().getUri().equals(uri);
}
}
public static class RequestMatcherBuilder implements RequestMatcher {
private String method;
private String hostname;
private String path;
private boolean noParams;
private Map<String, String> params = new HashMap<String, String>();
public RequestMatcherBuilder method(String method) {
this.method = method;
return this;
}
public RequestMatcherBuilder host(String hostname) {
this.hostname = hostname;
return this;
}
public RequestMatcherBuilder path(String path) {
this.path = "/" + path;
return this;
}
public RequestMatcherBuilder param(String name, String value) {
params.put(name, value);
return this;
}
public RequestMatcherBuilder noParams() {
noParams = true;
return this;
}
@Override public boolean matches(HttpRequest request) {
URI uri = URI.create(request.getRequestLine().getUri());
if (method != null && !method.equals(request.getRequestLine().getMethod())) return false;
if (hostname != null && !hostname.equals(uri.getHost())) return false;
if (path != null && !path.equals(uri.getRawPath())) return false;
if (noParams && !uri.getRawQuery().equals(null)) return false;
if (params.size() > 0) {
StringTokenizer tok = new StringTokenizer(uri.getRawQuery(), "&", false);
if (tok.countTokens() != params.size()) return false;
while (tok.hasMoreTokens()) {
String name, value;
String nextParam = tok.nextToken();
if (nextParam.contains("=")) {
String[] nameAndValue = nextParam.split("=");
name = nameAndValue[0];
value = nameAndValue[1];
} else {
name = nextParam;
value = "";
}
if (!params.get(name).equals(value)) return false;
}
}
return true;
}
}
// TODO: test this
public static class UriRegexMatcher implements RequestMatcher {
private String method;
private final Pattern uriRegex;
public UriRegexMatcher(String method, String uriRegex) {
this.method = method;
this.uriRegex = Pattern.compile(uriRegex);
}
@Override public boolean matches(HttpRequest request) {
return request.getRequestLine().getMethod().equals(method) &&
uriRegex.matcher(request.getRequestLine().getUri()).matches();
}
}
}