package org.jboss.resteasy.client.core.executors;
import org.jboss.resteasy.client.ClientExecutor;
import org.jboss.resteasy.client.ClientRequest;
import org.jboss.resteasy.client.ClientResponse;
import org.jboss.resteasy.client.core.BaseClientResponse;
import org.jboss.resteasy.client.core.BaseClientResponse.BaseClientResponseStreamFactory;
import org.jboss.resteasy.core.Dispatcher;
import org.jboss.resteasy.core.SynchronousDispatcher;
import org.jboss.resteasy.mock.MockHttpRequest;
import org.jboss.resteasy.mock.MockHttpResponse;
import org.jboss.resteasy.specimpl.MultivaluedMapImpl;
import org.jboss.resteasy.spi.Registry;
import org.jboss.resteasy.spi.ResteasyProviderFactory;
import javax.ws.rs.core.HttpHeaders;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.core.UriBuilder;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
@SuppressWarnings("unchecked")
public class InMemoryClientExecutor implements ClientExecutor
{
protected Dispatcher dispatcher;
protected URI baseUri;
public InMemoryClientExecutor()
{
dispatcher = new SynchronousDispatcher(ResteasyProviderFactory.getInstance());
}
public InMemoryClientExecutor(Dispatcher dispatcher)
{
this.dispatcher = dispatcher;
}
public URI getBaseUri()
{
return baseUri;
}
public void setBaseUri(URI baseUri)
{
this.baseUri = baseUri;
}
public ClientRequest createRequest(String uriTemplate)
{
return new ClientRequest(uriTemplate, this);
}
public ClientRequest createRequest(UriBuilder uriBuilder)
{
return new ClientRequest(uriBuilder, this);
}
public ClientResponse execute(ClientRequest request) throws Exception
{
MockHttpRequest mockHttpRequest = MockHttpRequest.create(request.getHttpMethod(), new URI(request.getUri()),
baseUri);
loadHttpMethod(request, mockHttpRequest);
final MockHttpResponse mockResponse = new MockHttpResponse();
dispatcher.invoke(mockHttpRequest, mockResponse);
return createResponse(request, mockResponse);
}
protected BaseClientResponse createResponse(ClientRequest request, final MockHttpResponse mockResponse)
{
BaseClientResponseStreamFactory streamFactory = createStreamFactory(mockResponse);
BaseClientResponse response = new BaseClientResponse(streamFactory, this);
response.setStatus(mockResponse.getStatus());
setHeaders(mockResponse, response);
response.setProviderFactory(request.getProviderFactory());
return response;
}
protected void setHeaders(final MockHttpResponse mockResponse, BaseClientResponse response)
{
MultivaluedMapImpl<String, String> responseHeaders = new MultivaluedMapImpl<String, String>();
for (Entry<String, List<Object>> entry : mockResponse.getOutputHeaders().entrySet())
{
List<String> values = new ArrayList<String>(entry.getValue().size());
for (Object value : entry.getValue())
{
values.add(value.toString());
}
responseHeaders.addMultiple(entry.getKey(), values);
}
response.setHeaders(responseHeaders);
}
public static BaseClientResponseStreamFactory createStreamFactory(final MockHttpResponse mockResponse)
{
return new BaseClientResponseStreamFactory()
{
InputStream stream;
public InputStream getInputStream() throws IOException
{
if (stream == null)
{
stream = new ByteArrayInputStream(mockResponse.getOutput());
}
return stream;
}
public void performReleaseConnection()
{
}
};
}
public void loadHttpMethod(ClientRequest request, MockHttpRequest mockHttpRequest) throws Exception
{
// TODO: punt on redirects, for now.
// if (httpMethod instanceof GetMethod && request.followRedirects())
// httpMethod.setFollowRedirects(true);
// else httpMethod.setFollowRedirects(false);
if (request.getBody() != null && !request.getFormParameters().isEmpty())
throw new RuntimeException("You cannot send both form parameters and an entity body");
if (!request.getFormParameters().isEmpty())
{
commitHeaders(request, mockHttpRequest);
for (Map.Entry<String, List<String>> formParam : request.getFormParameters().entrySet())
{
String key = formParam.getKey();
for (String value : formParam.getValue())
{
mockHttpRequest.getFormParameters().add(key, value);
}
}
}
else if (request.getBody() != null)
{
ByteArrayOutputStream baos = new ByteArrayOutputStream();
MediaType bodyContentType = request.getBodyContentType();
request.getHeadersAsObjects().add(HttpHeaders.CONTENT_TYPE, bodyContentType.toString());
request.writeRequestBody(request.getHeadersAsObjects(), baos);
// commit headers after byte array is complete.
commitHeaders(request, mockHttpRequest);
mockHttpRequest.content(baos.toByteArray());
mockHttpRequest.contentType(bodyContentType);
}
else
{
commitHeaders(request, mockHttpRequest);
}
}
public void commitHeaders(ClientRequest request, MockHttpRequest mockHttpRequest)
{
MultivaluedMap headers = mockHttpRequest.getHttpHeaders().getRequestHeaders();
headers.putAll(request.getHeaders());
}
private void setBody(ClientRequest request, MockHttpRequest mockHttpRequest) throws IOException
{
if (request.getBody() == null)
return;
}
public Registry getRegistry()
{
return this.dispatcher.getRegistry();
}
public Dispatcher getDispatcher()
{
return dispatcher;
}
}