// Path: src/main/java/com/googlecode/jsonrpc4j/JsonRpcBasicServer.java
// public static final String ERROR = "error";
// 
// Path: src/main/java/com/googlecode/jsonrpc4j/JsonRpcBasicServer.java
// public static final String ID = "id";
// 
// Path: src/main/java/com/googlecode/jsonrpc4j/JsonRpcBasicServer.java
// public static final String JSONRPC = "jsonrpc";
// 
// Path: src/main/java/com/googlecode/jsonrpc4j/JsonRpcBasicServer.java
// public static final String METHOD = "method";
// 
// Path: src/main/java/com/googlecode/jsonrpc4j/JsonRpcBasicServer.java
// public static final String PARAMS = "params";
// 
// Path: src/main/java/com/googlecode/jsonrpc4j/JsonRpcBasicServer.java
// public static final String RESULT = "result";


import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import org.apache.http.HttpEntity;
import org.apache.http.HttpEntityEnclosingRequest;
import org.apache.http.HttpHost;
import org.apache.http.HttpRequest;
import org.apache.http.HttpResponse;
import org.apache.http.StatusLine;
import org.apache.http.concurrent.FutureCallback;
import org.apache.http.config.ConnectionConfig;
import org.apache.http.entity.ByteArrayEntity;
import org.apache.http.entity.ContentType;
import org.apache.http.impl.DefaultConnectionReuseStrategy;
import org.apache.http.impl.nio.DefaultHttpClientIODispatch;
import org.apache.http.impl.nio.pool.BasicNIOConnFactory;
import org.apache.http.impl.nio.pool.BasicNIOConnPool;
import org.apache.http.impl.nio.reactor.DefaultConnectingIOReactor;
import org.apache.http.impl.nio.reactor.IOReactorConfig;
import org.apache.http.message.BasicHttpEntityEnclosingRequest;
import org.apache.http.nio.protocol.BasicAsyncRequestProducer;
import org.apache.http.nio.protocol.BasicAsyncResponseConsumer;
import org.apache.http.nio.protocol.HttpAsyncRequestExecutor;
import org.apache.http.nio.protocol.HttpAsyncRequester;
import org.apache.http.nio.reactor.ConnectingIOReactor;
import org.apache.http.nio.reactor.IOEventDispatch;
import org.apache.http.nio.reactor.IOReactorException;
import org.apache.http.protocol.BasicHttpContext;
import org.apache.http.protocol.HttpProcessor;
import org.apache.http.protocol.ImmutableHttpProcessor;
import org.apache.http.protocol.RequestConnControl;
import org.apache.http.protocol.RequestContent;
import org.apache.http.protocol.RequestExpectContinue;
import org.apache.http.protocol.RequestTargetHost;
import org.apache.http.protocol.RequestUserAgent;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.net.ssl.SSLContext;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InterruptedIOException;
import java.lang.reflect.Type;
import java.net.URL;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import static com.googlecode.jsonrpc4j.JsonRpcBasicServer.ERROR;
import static com.googlecode.jsonrpc4j.JsonRpcBasicServer.ID;
import static com.googlecode.jsonrpc4j.JsonRpcBasicServer.JSONRPC;
import static com.googlecode.jsonrpc4j.JsonRpcBasicServer.METHOD;
import static com.googlecode.jsonrpc4j.JsonRpcBasicServer.PARAMS;
import static com.googlecode.jsonrpc4j.JsonRpcBasicServer.RESULT;
	
	/**
	 * Set the request headers.
	 *
	 * @param request the request object
	 * @param headers to be used
	 */
	private void addHeaders(HttpRequest request, Map<String, String> headers) {
		for (Map.Entry<String, String> key : headers.entrySet()) {
			request.addHeader(key.getKey(), key.getValue());
		}
	}
	
	/**
	 * Writes a request.
	 *
	 * @param methodName  the method name
	 * @param arguments   the arguments
	 * @param httpRequest the stream on error
	 */
	private void writeRequest(String methodName, Object arguments, HttpRequest httpRequest) throws IOException {
		
		ObjectNode request = mapper.createObjectNode();
		request.put(ID, nextId.getAndIncrement());
		request.put(JSONRPC, JsonRpcBasicServer.VERSION);
		request.put(METHOD, methodName);
		
		if (arguments != null && arguments.getClass().isArray()) {
			Object[] args = Object[].class.cast(arguments);
			if (args.length > 0) {
// Path: src/main/java/com/googlecode/jsonrpc4j/JsonRpcBasicServer.java
// public static final String ERROR = "error";
// 
// Path: src/main/java/com/googlecode/jsonrpc4j/JsonRpcBasicServer.java
// public static final String ID = "id";
// 
// Path: src/main/java/com/googlecode/jsonrpc4j/JsonRpcBasicServer.java
// public static final String JSONRPC = "jsonrpc";
// 
// Path: src/main/java/com/googlecode/jsonrpc4j/JsonRpcBasicServer.java
// public static final String METHOD = "method";
// 
// Path: src/main/java/com/googlecode/jsonrpc4j/JsonRpcBasicServer.java
// public static final String PARAMS = "params";
// 
// Path: src/main/java/com/googlecode/jsonrpc4j/JsonRpcBasicServer.java
// public static final String RESULT = "result";


// Path: src/main/java/com/googlecode/jsonrpc4j/JsonRpcHttpAsyncClient.java
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import org.apache.http.HttpEntity;
import org.apache.http.HttpEntityEnclosingRequest;
import org.apache.http.HttpHost;
import org.apache.http.HttpRequest;
import org.apache.http.HttpResponse;
import org.apache.http.StatusLine;
import org.apache.http.concurrent.FutureCallback;
import org.apache.http.config.ConnectionConfig;
import org.apache.http.entity.ByteArrayEntity;
import org.apache.http.entity.ContentType;
import org.apache.http.impl.DefaultConnectionReuseStrategy;
import org.apache.http.impl.nio.DefaultHttpClientIODispatch;
import org.apache.http.impl.nio.pool.BasicNIOConnFactory;
import org.apache.http.impl.nio.pool.BasicNIOConnPool;
import org.apache.http.impl.nio.reactor.DefaultConnectingIOReactor;
import org.apache.http.impl.nio.reactor.IOReactorConfig;
import org.apache.http.message.BasicHttpEntityEnclosingRequest;
import org.apache.http.nio.protocol.BasicAsyncRequestProducer;
import org.apache.http.nio.protocol.BasicAsyncResponseConsumer;
import org.apache.http.nio.protocol.HttpAsyncRequestExecutor;
import org.apache.http.nio.protocol.HttpAsyncRequester;
import org.apache.http.nio.reactor.ConnectingIOReactor;
import org.apache.http.nio.reactor.IOEventDispatch;
import org.apache.http.nio.reactor.IOReactorException;
import org.apache.http.protocol.BasicHttpContext;
import org.apache.http.protocol.HttpProcessor;
import org.apache.http.protocol.ImmutableHttpProcessor;
import org.apache.http.protocol.RequestConnControl;
import org.apache.http.protocol.RequestContent;
import org.apache.http.protocol.RequestExpectContinue;
import org.apache.http.protocol.RequestTargetHost;
import org.apache.http.protocol.RequestUserAgent;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.net.ssl.SSLContext;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InterruptedIOException;
import java.lang.reflect.Type;
import java.net.URL;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import static com.googlecode.jsonrpc4j.JsonRpcBasicServer.ERROR;
import static com.googlecode.jsonrpc4j.JsonRpcBasicServer.ID;
import static com.googlecode.jsonrpc4j.JsonRpcBasicServer.JSONRPC;
import static com.googlecode.jsonrpc4j.JsonRpcBasicServer.METHOD;
import static com.googlecode.jsonrpc4j.JsonRpcBasicServer.PARAMS;
import static com.googlecode.jsonrpc4j.JsonRpcBasicServer.RESULT;

	
	/**
	 * Set the request headers.
	 *
	 * @param request the request object
	 * @param headers to be used
	 */
	private void addHeaders(HttpRequest request, Map<String, String> headers) {
		for (Map.Entry<String, String> key : headers.entrySet()) {
			request.addHeader(key.getKey(), key.getValue());
		}
	}
	
	/**
	 * Writes a request.
	 *
	 * @param methodName  the method name
	 * @param arguments   the arguments
	 * @param httpRequest the stream on error
	 */
	private void writeRequest(String methodName, Object arguments, HttpRequest httpRequest) throws IOException {
		
		ObjectNode request = mapper.createObjectNode();
		request.put(ID, nextId.getAndIncrement());
		request.put(JSONRPC, JsonRpcBasicServer.VERSION);
		request.put(METHOD, methodName);
		
		if (arguments != null && arguments.getClass().isArray()) {
			Object[] args = Object[].class.cast(arguments);
			if (args.length > 0) {
				request.set(PARAMS, mapper.valueToTree(Object[].class.cast(arguments)));