/*
* Copyright 2014, The Sporting Exchange Limited
* Copyright 2015, Simon Matić Langford
*
* 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 com.betfair.cougar.client;
import com.betfair.cougar.api.ExecutionContext;
import com.betfair.cougar.api.ExecutionContextImpl;
import com.betfair.cougar.api.export.Protocol;
import com.betfair.cougar.api.geolocation.GeoLocationDetails;
import com.betfair.cougar.api.security.IdentityResolver;
import com.betfair.cougar.api.security.IdentityChain;
import com.betfair.cougar.api.security.IdentityToken;
import com.betfair.cougar.api.security.IdentityTokenResolver;
import com.betfair.cougar.client.exception.HTTPErrorToCougarExceptionTransformer;
import com.betfair.cougar.client.query.QueryStringGenerator;
import com.betfair.cougar.client.query.QueryStringGeneratorFactory;
import com.betfair.cougar.core.api.ServiceDefinition;
import com.betfair.cougar.core.api.ServiceVersion;
import com.betfair.cougar.core.api.ev.*;
import com.betfair.cougar.core.api.tracing.Tracer;
import com.betfair.cougar.core.api.transcription.Parameter;
import com.betfair.cougar.core.api.transcription.ParameterType;
import com.betfair.cougar.core.impl.DefaultTimeConstraints;
import com.betfair.cougar.logging.CougarLoggingUtils;
import com.betfair.cougar.util.RequestUUIDImpl;
import com.betfair.cougar.util.UUIDGeneratorImpl;
import org.slf4j.LoggerFactory;
import com.betfair.cougar.marshalling.api.databinding.DataBindingFactory;
import com.betfair.cougar.marshalling.api.databinding.FaultMarshaller;
import com.betfair.cougar.marshalling.api.databinding.Marshaller;
import com.betfair.cougar.marshalling.api.databinding.UnMarshaller;
import com.betfair.cougar.transport.api.protocol.http.HttpServiceBindingDescriptor;
import com.betfair.cougar.transport.api.protocol.http.rescript.RescriptBody;
import com.betfair.cougar.transport.api.protocol.http.rescript.RescriptOperationBindingDescriptor;
import com.betfair.cougar.transport.api.protocol.http.rescript.RescriptParamBindingDescriptor;
import com.betfair.cougar.transport.api.protocol.http.rescript.RescriptResponse;
import org.apache.http.client.methods.HttpUriRequest;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
import javax.servlet.http.HttpServletResponse;
import javax.xml.bind.annotation.XmlElement;
import java.io.IOException;
import java.io.InputStream;
import java.util.*;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicInteger;
import static org.junit.Assert.*;
import static org.junit.Assert.assertEquals;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyString;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.*;
/**
* Date: 28/01/2013
* Time: 14:48
*/
public abstract class AbstractHttpExecutableTest<HttpRequest> {
protected AbstractHttpExecutable<HttpRequest> client;
protected static final String SERVER_URI = "http://localhost:9001/";
protected static final String TEST_TEXT = "hello";
protected TestServiceDefinition tsd;
protected QueryStringGeneratorFactory qsgf;
protected QueryStringGenerator queryStringGenerator;
protected Marshaller mockedMarshaller;
protected UnMarshaller mockedUnMarshaller;
protected FaultMarshaller mockedFaultMarshaller;
protected HTTPErrorToCougarExceptionTransformer mockedHttpErrorTransformer;
protected CougarRequestFactory<HttpRequest> mockMethodFactory;
protected ExecutionVenue ev;
protected HttpRequest mockGetMethod;
protected HttpRequest mockPostMethod;
protected PassFailExecutionObserver observer;
protected Tracer tracer;
@BeforeClass
public static void suppressLogs() {
CougarLoggingUtils.suppressAllRootLoggerOutput();
}
private Answer<HttpRequest> httpMethodFactoryCreatePostAnswer = new Answer<HttpRequest>() {
public HttpRequest answer(InvocationOnMock invocation) throws Throwable {
Object[] args = invocation.getArguments();
String uri = (String)args[0];
String httpMethodString = (String)args[1];
Message message = (Message)args[2];
Marshaller marshaller = (Marshaller)args[3];
String contentType = (String)args[4];
assertEquals(SERVER_URI + "test/v1/post", uri);
assertEquals("POST", httpMethodString);
assertEquals(0, message.getHeaderMap().size());
assertEquals(0, message.getQueryParmMap().size());
assertEquals(1, message.getRequestBodyMap().size());
assertTrue(message.getRequestBodyMap().containsKey("messagePOST"));
assertNotNull(marshaller);
assertEquals("application/json", contentType);
return mockPostMethod;
}
};
private Answer<HttpRequest> httpMethodFactoryCreateMixedAnswer = new Answer<HttpRequest>() {
public HttpRequest answer(InvocationOnMock invocation) throws Throwable {
Object[] args = invocation.getArguments();
String uri = (String)args[0];
String httpMethodString = (String)args[1];
Message message = (Message)args[2];
Marshaller marshaller = (Marshaller)args[3];
String contentType = (String)args[4];
assertEquals(SERVER_URI + "test/v1/mixed?messageMixedQUERY=hello", uri);
assertEquals("POST", httpMethodString);
assertEquals(0, message.getHeaderMap().size());
assertEquals(1, message.getQueryParmMap().size());
assertTrue(message.getQueryParmMap().containsKey("messageMixedQUERY"));
assertEquals(1, message.getRequestBodyMap().size());
assertTrue(message.getRequestBodyMap().containsKey("messageMixedPOST"));
assertNotNull(marshaller);
assertEquals("application/json", contentType);
return mockPostMethod;
}
};
@Before
public void setup() throws Exception {
// Add dependent mocks to cougar client execution venue
tsd = new TestServiceDefinition();
TestServiceBindingDescriptor tsbd = new TestServiceBindingDescriptor();
RequestUUIDImpl.setGenerator(new UUIDGeneratorImpl());
tracer = mock(Tracer.class);
client = makeExecutable(tsbd);
mockedMarshaller = mock(Marshaller.class);
mockedUnMarshaller = mock(UnMarshaller.class);
mockedFaultMarshaller = mock(FaultMarshaller.class);
mockedHttpErrorTransformer = mock(HTTPErrorToCougarExceptionTransformer.class);
mockMethodFactory = mock(CougarRequestFactory.class);
when(mockMethodFactory.create(any(String.class), any(String.class), any(Message.class), any(Marshaller.class),
any(String.class), any(ClientCallContext.class), any(TimeConstraints.class))).thenReturn(mockGetMethod);
qsgf = mock(QueryStringGeneratorFactory.class);
queryStringGenerator = mock(QueryStringGenerator.class);
when(qsgf.getQueryStringGenerator()).thenReturn(queryStringGenerator);
client.setRequestFactory(mockMethodFactory);
client.setQueryStringGeneratorFactory(qsgf);
DataBindingFactory mockedBindingFactory = mock(DataBindingFactory.class);
when(mockedBindingFactory.getMarshaller()).thenReturn(mockedMarshaller);
when(mockedBindingFactory.getUnMarshaller()).thenReturn(mockedUnMarshaller);
when(mockedBindingFactory.getFaultMarshaller()).thenReturn(mockedFaultMarshaller);
client.setDataBindingFactory(mockedBindingFactory);
client.setRemoteAddress(SERVER_URI);
preInit();
client.init();
}
protected void preInit() throws Exception {
}
protected abstract AbstractHttpExecutable<HttpRequest> makeExecutable(HttpServiceBindingDescriptor tsbd)
throws Exception;
protected void generateEV(TestServiceDefinition tsd, String namespace) {
ev = mock(ExecutionVenue.class);
OperationDefinition[] opDefs = tsd.getOperationDefinitions();
final Map<OperationKey, OperationDefinition> opMap = new HashMap<OperationKey, OperationDefinition>();
for (OperationDefinition od : opDefs) {
if (namespace == null) {
opMap.put(od.getOperationKey(), od);
} else {
opMap.put(new OperationKey(od.getOperationKey(), namespace), od);
}
}
when(ev.getOperationKeys()).thenReturn(opMap.keySet());
when(ev.getOperationDefinition(any(OperationKey.class))).thenAnswer(new Answer<OperationDefinition>() {
@Override
public OperationDefinition answer(InvocationOnMock invocation) throws Throwable {
OperationKey opKey = (OperationKey) invocation.getArguments()[0];
return opMap.get(opKey);
}
});
}
public void makeSimpleCall(ExecutionContext ec) throws Exception {
String response = "{\"result\":\"" + TEST_TEXT + "\"}";
when(mockMethodFactory.create(anyString(), anyString(), any(Message.class), any(Marshaller.class),
anyString(), any(ClientCallContext.class), any(TimeConstraints.class))).thenReturn(mockGetMethod);
observer = new PassFailExecutionObserver(true, false);
OperationKey key = TestServiceDefinition.TEST_GET;
TestResponse tr = new TestResponse();
tr.setResult(TEST_TEXT);
when(mockedUnMarshaller.unmarshall(any(InputStream.class),
any(ParameterType.class), anyString(), eq(true))).thenReturn(tr);
mockAndMakeCall(mockGetMethod, HttpServletResponse.SC_OK, response, 18, client, ec, key, new Object[]{TEST_TEXT}, observer, ev, DefaultTimeConstraints.NO_CONSTRAINTS);
TestResponse resp = (TestResponse)observer.getResult().getResult();
assertEquals(TEST_TEXT, resp.getResult());
assertEquals(ExecutionResult.ResultType.Success, observer.getResult().getResultType());
assertEquals(18, ((ClientExecutionResult)observer.getResult()).getResultSize());
}
@Test
public void testEVGetSuccess() throws Exception {
generateEV(tsd, null);
makeSimpleCall(createEC(null, null, false));
}
@Test
public void testIdentityTokenWriting() throws Exception {
IdentityResolver resolver = mock((IdentityResolver.class));
IdentityTokenResolver tokenResolver = mock((IdentityTokenResolver.class));
client.setIdentityResolver(resolver);
client.setIdentityTokenResolver(tokenResolver);
when(tokenResolver.isRewriteSupported()).thenReturn(true);
final List<IdentityToken> tokens = new ArrayList<IdentityToken>();
when(resolver.tokenise(any(IdentityChain.class))).thenReturn(tokens);
generateEV(tsd, null);
makeSimpleCall(createEC(null, null, true));
verify(resolver).tokenise(any(IdentityChain.class));
verify(tokenResolver).rewrite(eq(tokens), any(HttpUriRequest.class));
}
@Test
public void testIdentityTokenWritingRewriteOff() throws Exception {
IdentityResolver resolver = mock((IdentityResolver.class));
IdentityTokenResolver tokenResolver = mock((IdentityTokenResolver.class));
client.setIdentityResolver(resolver);
client.setIdentityTokenResolver(tokenResolver);
when(tokenResolver.isRewriteSupported()).thenReturn(false);
final List<IdentityToken> tokens = new ArrayList<IdentityToken>();
when(resolver.tokenise(any(IdentityChain.class))).thenReturn(tokens);
generateEV(tsd, null);
makeSimpleCall(createEC(null, null, true));
verify(resolver, never()).tokenise(any(IdentityChain.class));
verify(tokenResolver, never()).rewrite(eq(tokens), any(HttpUriRequest.class));
}
@Test
public void testEVGetSuccessWithNamespaceMatch() throws Exception {
generateEV(tsd, "MyNamespace");
String response = "{\"result\":\"" + TEST_TEXT + "\"}";
when(mockMethodFactory.create(anyString(), anyString(), any(Message.class), any(Marshaller.class),
anyString(), any(ClientCallContext.class), any(TimeConstraints.class))).thenReturn(mockGetMethod);
TestResponse testResponse = new TestResponse();
testResponse.setResult(TEST_TEXT);
OperationKey key = new OperationKey(TestServiceDefinition.TEST_GET, "MyNamespace");
observer = new PassFailExecutionObserver(true, false);
TestResponse tr = new TestResponse();
tr.setResult(TEST_TEXT);
when(mockedUnMarshaller.unmarshall(any(InputStream.class),
any(ParameterType.class), anyString(), eq(true))).thenReturn(tr);
mockAndMakeCall(mockGetMethod, HttpServletResponse.SC_OK, response, 18, client, createEC(null, null, false), key, new Object[]{TEST_TEXT}, observer, ev, DefaultTimeConstraints.NO_CONSTRAINTS);
TestResponse resp = (TestResponse)observer.getResult().getResult();
assertEquals(TEST_TEXT, resp.getResult());
assertEquals(ExecutionResult.ResultType.Success, observer.getResult().getResultType());
assertEquals(18, ((ClientExecutionResult)observer.getResult()).getResultSize());
}
@Test
public void testEVFailWrongNamespace() {
generateEV(tsd, "MyNamespace");
OperationKey key = new OperationKey(TestServiceDefinition.TEST_GET, "WrongNamespace");
observer = new PassFailExecutionObserver(true, false);
try {
client.execute(createEC(null, null, false), key, new Object[] {TEST_TEXT }, observer, ev, DefaultTimeConstraints.NO_CONSTRAINTS);
} catch (NullPointerException e) {
// correct - the provided key was not right
assert true;
}
}
@Test
public void testEVFailNoNamespaceProvided() {
generateEV(tsd, "MyNamespace");
OperationKey key = TestServiceDefinition.TEST_GET;
observer = new PassFailExecutionObserver(true, false);
try {
client.execute(createEC(null, null, false), key, new Object[] {TEST_TEXT }, observer, ev, DefaultTimeConstraints.NO_CONSTRAINTS);
} catch (NullPointerException e) {
// correct - the provided key was not right
}
}
@Test
public void changeRemoteAddress() throws InterruptedException {
generateEV(tsd, null);
final int maxThreads = 5;
Thread[] threads = new Thread[maxThreads];
final OperationKey key = new OperationKey(TestServiceDefinition.TEST_GET, null);
final AtomicInteger failureCount = new AtomicInteger(0);
for (int threadCount = 0; threadCount < maxThreads; threadCount++) {
final Integer threadId = new Integer(threadCount);
Thread t = new Thread(new Runnable() {
@Override
public void run() {
int iterations = 100;
ExecutionContext ec = createEC(null, null, false);
do {
observer = new PassFailExecutionObserver(true, true) {
@Override
public void onResult(ExecutionResult executionResult) {
}
};
try {
client.execute(ec, key, new Object[] {TEST_TEXT }, observer, ev, DefaultTimeConstraints.NO_CONSTRAINTS);
if (iterations % 5 == 0 && threadId == 0) {
client.setRemoteAddress("http://localhost:" + iterations + "/");
}
} catch (Exception ex) {
failureCount.incrementAndGet();
}
} while (--iterations > 0);
}
});
threads[threadCount] = t;
t.start();
}
for (int i = 0; i < maxThreads; i++) {
threads[i].join();
}
if (failureCount.get() > 0) {
fail("An exception occurred during multithreaded test of remote address modification");
}
}
@Test
public void testEVFailNoNamespaceRegistered() {
generateEV(tsd, null);
OperationKey key = new OperationKey(TestServiceDefinition.TEST_GET, "MyNamespace");
observer = new PassFailExecutionObserver(true, false);
try {
client.execute(createEC(null, null, false), key, new Object[] {TEST_TEXT }, observer, ev, DefaultTimeConstraints.NO_CONSTRAINTS);
} catch (NullPointerException e) {
// correct - the provided key was not right
}
}
@Test
public void testEVPostSuccessWithMandatoryBodyParameterPresent() throws Exception {
generateEV(tsd, null);
when(queryStringGenerator.generate(any(Map.class))).thenReturn("");
when(mockMethodFactory.create(anyString(), anyString(), any(Message.class), any(Marshaller.class),
anyString(), any(ClientCallContext.class), any(TimeConstraints.class))).thenAnswer(httpMethodFactoryCreatePostAnswer);
String response = "{\"result\":\"" + TEST_TEXT + "\"}";
TestResponse tr = new TestResponse();
tr.setResult(TEST_TEXT);
when(mockedUnMarshaller.unmarshall(any(InputStream.class), any(ParameterType.class),
anyString(), eq(true))).thenReturn(tr);
TestResponse testResponse = new TestResponse();
testResponse.setResult(TEST_TEXT);
OperationKey key = TestServiceDefinition.TEST_POST;
observer = new PassFailExecutionObserver(true, false);
mockAndMakeCall(mockPostMethod, HttpServletResponse.SC_OK, response, 18, client, createEC(null, null, false), key, new Object[]{TEST_TEXT}, observer, ev, DefaultTimeConstraints.NO_CONSTRAINTS);
TestResponse resp = (TestResponse)observer.getResult().getResult();
assertEquals(TEST_TEXT, resp.getResult());
assertEquals(ExecutionResult.ResultType.Success, observer.getResult().getResultType());
assertEquals(18, ((ClientExecutionResult)observer.getResult()).getResultSize());
}
@Test
public void testEVPostSuccessWithMandatoryBodyAndQueryParameterPresent() throws Exception {
generateEV(tsd, null);
when(queryStringGenerator.generate(any(Map.class))).thenReturn("?messageMixedQUERY=hello");
when(mockMethodFactory.create(anyString(), anyString(), any(Message.class), any(Marshaller.class),
anyString(), any(ClientCallContext.class), any(TimeConstraints.class))).thenAnswer(httpMethodFactoryCreateMixedAnswer);
String response = "{\"result\":\"" + TEST_TEXT + TEST_TEXT + "\"}";
TestResponse testResponse = new TestResponse();
testResponse.setResult(TEST_TEXT + TEST_TEXT);
OperationKey key = TestServiceDefinition.TEST_MIXED;
observer = new PassFailExecutionObserver(true, false);
when(mockedUnMarshaller.unmarshall(any(InputStream.class), any(ParameterType.class), anyString(), eq(true)))
.thenReturn(testResponse);
mockAndMakeCall(mockPostMethod, HttpServletResponse.SC_OK, response, 18, client, createEC(null, null, false), key, new Object[]{TEST_TEXT, TEST_TEXT}, observer, ev, DefaultTimeConstraints.NO_CONSTRAINTS);
TestResponse resp = (TestResponse)observer.getResult().getResult();
assertEquals(TEST_TEXT + TEST_TEXT, resp.getResult());
assertEquals(ExecutionResult.ResultType.Success, observer.getResult().getResultType());
assertEquals(getEVPostSuccessWithMandatoryBodyAndQueryParameterPresent_ResultSize(), ((ClientExecutionResult)observer.getResult()).getResultSize());
}
protected abstract int getEVPostSuccessWithMandatoryBodyAndQueryParameterPresent_ResultSize();
@Test(expected = IllegalArgumentException.class)
public void testExtractPortFromBadAddresses() throws IOException {
HttpClientExecutable executable = new HttpClientExecutable(null, new HttpContextEmitter(new DefaultGeoLocationSerializer(),"X-REQUEST-UUID","X-REQUEST-UUID-PARENTS"),tracer);
executable.setRemoteAddress("NOT ASSIGNED");
executable.extractPortFromAddress();
}
@Test
public void testExtractPortFromAddress() throws IOException {
HttpClientExecutable executable = new HttpClientExecutable(null, new HttpContextEmitter(new DefaultGeoLocationSerializer(),"X-REQUEST-UUID","X-REQUEST-UUID-PARENTS"),tracer);
executable.setRemoteAddress("http://wibble.com:3939/www");
int actual = executable.extractPortFromAddress();
assertEquals(3939, actual);
executable.setRemoteAddress("http://wibble.com:25000");
actual = executable.extractPortFromAddress();
assertEquals(25000, actual);
}
protected ExecutionContext createEC(final String remoteIp, final String customerIp, boolean trace) {
ExecutionContextImpl eci = new ExecutionContextImpl();
eci.setTraceLoggingEnabled(trace);
if (remoteIp != null || customerIp != null) {
GeoLocationDetails gld = new GeoLocationDetails() {
@Override
public String getRemoteAddr() {
return remoteIp;
}
@Override
public List<String> getResolvedAddresses() {
return Collections.singletonList(customerIp);
}
@Override
public String getCountry() {
return null;
}
@Override
public boolean isLowConfidenceGeoLocation() {
return false;
}
@Override
public String getLocation() {
return null;
}
@Override
public String getInferredCountry() {
return null;
}
};
eci.setGeoLocationDetails(gld);
}
return eci;
}
protected static class TestServiceDefinition extends ServiceDefinition {
private static final String SERVICE_NAME = "test";
private static final ServiceVersion SERVICE_VERSION = new ServiceVersion("v1.0");
public static final OperationKey TEST_GET = new OperationKey(SERVICE_VERSION, SERVICE_NAME,
"TEST_GET", OperationKey.Type.Request);
public static final OperationKey TEST_POST = new OperationKey(SERVICE_VERSION, SERVICE_NAME,
"TEST_POST", OperationKey.Type.Request);
public static final OperationKey TEST_MIXED = new OperationKey(SERVICE_VERSION, SERVICE_NAME,
"TEST_MIXED", OperationKey.Type.Request);
private OperationDefinition[] operationDefinitions = new OperationDefinition[] {
new SimpleOperationDefinition(TEST_GET, new Parameter[] {
new Parameter("message", new ParameterType(String.class, null), true) },
new ParameterType(TestResponse.class, null)),
new SimpleOperationDefinition(TEST_POST, new Parameter [] {
new Parameter("messagePOST", new ParameterType(String.class, null), true) },
new ParameterType(TestResponse.class, null)),
new SimpleOperationDefinition(TEST_MIXED, new Parameter [] {
new Parameter("messageMixedPOST", new ParameterType(String.class, null), true),
new Parameter("messageMixedQUERY", new ParameterType(String.class, null), true) },
new ParameterType(TestResponse.class, null))
};
public TestServiceDefinition() {
super.init();
}
@Override
public String getServiceName() {
return SERVICE_NAME;
}
@Override
public ServiceVersion getServiceVersion() {
return SERVICE_VERSION;
}
@Override
public OperationDefinition[] getOperationDefinitions() {
return operationDefinitions;
}
}
protected static class PassFailExecutionObserver implements ExecutionObserver, ObservableObserver {
private boolean passOnResult;
private boolean passOnException;
private ExecutionResult result;
private CountDownLatch latch = new CountDownLatch(1);
protected PassFailExecutionObserver(boolean passOnResult, boolean passOnException) {
this.passOnResult = passOnResult;
this.passOnException = passOnException;
}
@Override
public void onResult(ExecutionResult result) {
this.result = result;
latch.countDown();
switch (result.getResultType()) {
case Success:
if (!passOnResult) {
fail("Did not expect a successful ExecutionResult");
}
break;
case Fault:
if (!passOnException) {
fail("Did not expect a fault ExecutionResult");
}
break;
default:
fail("Incorrect ExecutionResult type received: " + result.getResultType());
}
}
public ExecutionResult getResult() {
return result;
}
public CountDownLatch getLatch() {
return latch;
}
}
protected static class TestServiceBindingDescriptor implements HttpServiceBindingDescriptor {
private final ServiceVersion serviceVersion = new ServiceVersion("v1.0");
private final String serviceName = "test";
public TestServiceBindingDescriptor() {
List<RescriptParamBindingDescriptor> testGetParamBindings =
new ArrayList<RescriptParamBindingDescriptor>();
testGetParamBindings.add(new RescriptParamBindingDescriptor("message",
RescriptParamBindingDescriptor.ParamSource.QUERY));
testGetDescriptor = new RescriptOperationBindingDescriptor(TestServiceDefinition.TEST_GET,
"/get", "GET", testGetParamBindings, TestResponse.class);
List<RescriptParamBindingDescriptor> testPostParamBindings =
new ArrayList<RescriptParamBindingDescriptor>();
testPostParamBindings.add(new RescriptParamBindingDescriptor("messagePOST",
RescriptParamBindingDescriptor.ParamSource.BODY));
testPostDescriptor = new RescriptOperationBindingDescriptor(TestServiceDefinition.TEST_POST,
"/post", "POST", testPostParamBindings, TestResponse.class, TestBody.class);
List<RescriptParamBindingDescriptor> testMixedParamBindings =
new ArrayList<RescriptParamBindingDescriptor>();
testMixedParamBindings.add(new RescriptParamBindingDescriptor("messageMixedPOST",
RescriptParamBindingDescriptor.ParamSource.BODY));
testMixedParamBindings.add(new RescriptParamBindingDescriptor("messageMixedQUERY",
RescriptParamBindingDescriptor.ParamSource.QUERY));
testMixedDescriptor = new RescriptOperationBindingDescriptor(TestServiceDefinition.TEST_MIXED,
"/mixed", "POST", testMixedParamBindings, TestResponse.class, TestBody.class);
operations = new RescriptOperationBindingDescriptor[] {
testGetDescriptor,
testPostDescriptor,
testMixedDescriptor
};
}
@Override
public Protocol getServiceProtocol() {
return Protocol.RESCRIPT;
}
@Override
public String getServiceContextPath() {
return "/test/";
}
@Override
public RescriptOperationBindingDescriptor[] getOperationBindings() {
return operations;
}
@Override
public String getServiceName() {
return serviceName;
}
@Override
public ServiceVersion getServiceVersion() {
return serviceVersion;
}
private final RescriptOperationBindingDescriptor[] operations;
private final RescriptOperationBindingDescriptor testGetDescriptor;
private final RescriptOperationBindingDescriptor testPostDescriptor;
private final RescriptOperationBindingDescriptor testMixedDescriptor;
}
private static class TestBody implements RescriptBody {
private Map<String, Object> parameters = new HashMap<String, Object>();
@Override
public Object getValue(String name) {
return parameters.get(name);
}
private String message;
@XmlElement(name = "message")
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
parameters.put("message", message);
}
}
protected static class TestResponse implements RescriptResponse {
private Object result;
@Override
public Object getResult() {
return result;
}
@Override
public void setResult(Object result) {
this.result = result;
}
}
protected static interface ObservableObserver extends ExecutionObserver {
CountDownLatch getLatch();
}
protected abstract void mockAndMakeCall(HttpRequest request, int httpCode, String response, int responseSize,
AbstractHttpExecutable<HttpRequest> client, ExecutionContext ec, OperationKey key,
Object[] params, ObservableObserver observer, ExecutionVenue ev, TimeConstraints timeConstraints) throws InterruptedException;
}