package com.msgilligan.bitcoinj.rpc;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.io.IOException;
import java.net.URI;
import java.util.Arrays;
import java.util.List;
/**
* Abstract Base class for a strongly-typed JSON-RPC client
*/
public abstract class AbstractRPCClient implements UntypedRPCClient {
protected final ObjectMapper mapper;
private final JavaType defaultType;
public AbstractRPCClient() {
mapper = new ObjectMapper();
defaultType = mapper.getTypeFactory().constructType(Object.class);
}
public abstract URI getServerURI();
/**
* Subclasses must implement this method to actually send the request
* @param request The request to send
* @param responseType The response to expected (used by Jackson for conversion)
* @param pass:[<R>] Type of result object
* @return A JSON RPC Response with `result` of type `R`
* @throws IOException network error
* @throws JsonRPCStatusException JSON RPC status error
*/
protected abstract <R> JsonRpcResponse<R> send(JsonRpcRequest request, JavaType responseType) throws IOException, JsonRPCStatusException;
/**
* JSON-RPC remote method call that returns 'response.result`
*
* @param method JSON RPC method call to send
* @param params JSON RPC params
* @param pass:[<R>] Type of result object
* @param resultType desired result type as a Java class object
* @return the 'response.result' field of the JSON RPC response converted to type R
*/
protected <R> R send(String method, Class<R> resultType, List<Object> params) throws IOException, JsonRPCStatusException {
JsonRpcRequest request = new JsonRpcRequest(method, params);
// Construct a JavaType object so we can tell Jackson what type of result we are expecting.
// (We can't use R because of type erasure)
JavaType responseType = mapper.getTypeFactory().
constructParametrizedType(JsonRpcResponse.class, JsonRpcResponse.class, resultType);
JsonRpcResponse<R> response = send(request, responseType);
// assert response != null;
// assert response.getJsonrpc() != null;
// assert response.getJsonrpc().equals("2.0");
// assert response.getId() != null;
// assert response.getId().equals(request.getId());
return response.getResult();
}
/**
* Varargs version
*/
protected <R> R send(String method, Class<R> resultType, Object... params) throws IOException, JsonRPCStatusException {
return send(method, resultType, Arrays.asList(params));
}
/**
* JSON-RPC remote method call that returns 'response.result`
*
* @param pass:[<R>] Type of result object
* @param method JSON RPC method call to send
* @param params JSON RPC params
* @param resultType desired result type as a Jackson JavaType object
* @return the 'response.result' field of the JSON RPC response converted to type R
*/
protected <R> R send(String method, JavaType resultType, List<Object> params) throws IOException, JsonRPCStatusException {
JsonRpcRequest request = new JsonRpcRequest(method, params);
// Construct a JavaType object so we can tell Jackson what type of result we are expecting.
// (We can't use R because of type erasure)
JavaType responseType = mapper.getTypeFactory().
constructParametrizedType(JsonRpcResponse.class, JsonRpcResponse.class, resultType);
JsonRpcResponse<R> response = send(request, responseType);
return response.getResult();
}
/**
* Varargs version
*/
protected <R> R send(String method, JavaType resultType, Object... params) throws IOException, JsonRPCStatusException {
return send(method, resultType, Arrays.asList(params));
}
/**
* Call an RPC method and return default object type.
*
* Caller should cast returned object to the correct type.
*
* Useful for:
* * Simple (not client-side validated) command line utilities
* * Functional tests that need to send incorrect types to the server to test error handling
*
* @param method JSON RPC method call to send
* @param params JSON RPC params
* @param pass:[<R>] Type of result object
* @return the 'response.result' field of the JSON RPC response cast to type R
* @throws IOException network error
* @throws JsonRPCStatusException JSON RPC status error
*/
@Override
public <R> R send(String method, List<Object> params) throws IOException, JsonRPCStatusException {
return send(method, defaultType, params);
}
/**
* Call an RPC method and return default object type.
*
* Caller should cast returned object to the correct type.
*
* Useful for:
* * Simple (not client-side validated) command line utilities
* * Functional tests that need to send incorrect types to the server to test error handling
*
* @param method JSON RPC method call to send
* @param params JSON RPC params
* @param pass:[<R>] Type of result object
* @return the 'response.result' field of the JSON RPC response cast to type R
* @throws IOException network error
* @throws JsonRPCStatusException JSON RPC status error
*/
@Override
public <R> R send(String method, Object... params) throws IOException, JsonRPCStatusException {
return send(method, Arrays.asList(params));
}
}