package org.rackspace.stingray.client.mock; import com.sun.jersey.api.client.ClientHandler; import com.sun.jersey.api.client.ClientHandlerException; import com.sun.jersey.api.client.ClientRequest; import com.sun.jersey.api.client.ClientResponse; import com.sun.jersey.api.client.ClientResponse.Status; import org.apache.commons.lang.builder.EqualsBuilder; import org.apache.commons.lang.builder.HashCodeBuilder; import org.mockito.Mockito; import org.rackspace.stingray.client.exception.StingrayRestClientException; import org.rackspace.stingray.client.exception.StingrayRestClientObjectNotFoundException; import javax.ws.rs.core.Response; import java.util.HashMap; import java.util.Map; public final class MockClientHandler implements ClientHandler { public static final String ROOT = "https://localhost:9070/api/tm/1.0/config/active/"; private Map<Request, MockResponse> mocked = new HashMap<Request, MockResponse>(); @Override public ClientResponse handle(ClientRequest cr) throws ClientHandlerException { String uri = cr.getURI().toString(); String relative = uri.replace(ROOT, ""); Request request = new Request(relative, cr.getMethod()); MockResponse response = mocked.get(request); if (response == null) { throw new RuntimeException(String.format("Path %s for %s was not mocked", relative, cr.getMethod())); } if (response.exception != null) { throw new ClientHandlerException(response.exception); } if (response.clientResponse != null) { return response.clientResponse; } return null; } public ContinuedMocking when(String path, String method) { Request request = new Request(path, method); return new ContinuedMocking(mocked, request); } public static final class ContinuedMocking { private final Map<Request, MockResponse> mocked; private final Request request; private ContinuedMocking(final Map<Request, MockResponse> mocked, final Request request) { this.mocked = mocked; this.request = request; } public void thenReturn(final Response.Status status, final Object response) throws StingrayRestClientException, StingrayRestClientObjectNotFoundException { // TODO we might try to use the real response here // InBoundHeaders headers = new InBoundHeaders(); // MessageBodyWorkers workers = Mockito.mock(MessageBodyWorkers.class); // ClientResponse clientResponse = new ClientResponse(status.getStatusCode(), headers, new ByteArrayInputStream(response.getBytes()), workers); ClientResponse clientResponse = Mockito.mock(ClientResponse.class); Mockito.when(clientResponse.getStatus()).thenReturn(status.getStatusCode()); Mockito.when(clientResponse.getClientResponseStatus()).thenReturn(Status.fromStatusCode(status.getStatusCode())); Mockito.when(clientResponse.getEntity(Mockito.<Class>any())).thenReturn(response); //Failed attempts to update for bad requests... // if (status != Response.Status.ACCEPTED && status != Response.Status.OK) { // Mockito.when(clientResponse.getStatus()).thenReturn(status.getStatusCode()); // clientResponse.setStatus(status.getStatusCode()); // RequestManagerUtil rmu = Mockito.mock(RequestManagerUtil.class); // Mockito.doThrow(new StingrayRestClientException(String.format("Caused By: %s: Reason: %s: Additional: %s", // status, "something", "something ... darkside"))).when(rmu).buildFaultMessage(Matchers.<ClientResponse>any()); // // mocked.put(request, new MockResponse(null, new StingrayRestClientException(String.format("Caused By: %s: Reason: %s: Additional: %s", // status, "something", "something ... darkside")))); // } MockResponse mockResponse = new MockResponse(clientResponse, null); mocked.put(request, mockResponse); } public void thenThrow(final Exception exception) { mocked.put(request, new MockResponse(null, exception)); } } private static final class MockResponse { private final ClientResponse clientResponse; private final Exception exception; public MockResponse(final ClientResponse clientResponse, final Exception exception) { this.clientResponse = clientResponse; this.exception = exception; } } private static final class Request { private String path; private String method; public Request(final String path, final String method) { this.path = path; this.method = method; } @Override public boolean equals(Object obj) { return EqualsBuilder.reflectionEquals(this, obj); } @Override public int hashCode() { return new HashCodeBuilder(17, 37). append(path).append(method).toHashCode(); } } }