/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements. See the NOTICE file distributed with this
 * work for additional information regarding copyright ownership. The ASF
 * licenses this file to You 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 org.apache.sling.testing.clients;

import org.apache.http.*;
import org.apache.http.annotation.Immutable;
import org.apache.http.client.*;
import org.apache.http.client.methods.*;
import org.apache.http.client.protocol.HttpClientContext;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.message.BasicHttpRequest;
import org.apache.http.protocol.HttpContext;
import org.apache.sling.testing.clients.util.HttpUtils;
import org.slf4j.LoggerFactory;

import java.io.Closeable;
import java.io.IOException;
import java.lang.reflect.Constructor;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.List;
import java.util.Map;
import java.util.UUID;

/**
 * The abstract base client for all implementing integration test clients.
 */
@Immutable
public class AbstractSlingClient implements HttpClient, Closeable {

    private final org.slf4j.Logger log = LoggerFactory.getLogger(getClass());

    private final static URI slash = URI.create("/");

    /**
     * The clientId for the client, generated automatically during instantiation of client.
     */
    private final String clientId;

    /**
     * The HttpClient object to which http calls are delegated.
     * It can be shared across multiple AbstractSlingClients (by using adaptTo())
     */
    private final CloseableHttpClient http;

    /**
     * A wrapper object containing the sling config for this client.
     * It can be shared across multiple AbstractSlingClients (by using adaptTo())
     */
    private final SlingClientConfig config;

    /**
     * Constructor used by Builders and adaptTo(). <b>Should never be called directly from the code.</b>
     *
     * @param http http client to handle the delegated calls
     * @param config immutable object holding the config
     * @throws ClientException if the client could not be initialized
     */
    AbstractSlingClient(CloseableHttpClient http, SlingClientConfig config) throws ClientException {
        // Generate client ID
        this.clientId = this.getClass() + "-" + UUID.randomUUID().toString();
        this.http = http;
        this.config = config;
    }

    /**
     * Returns the unique id for this client, generated automatically during instantiation.<br>
     *
     * @return client's unique id
     */
    protected String getClientId() {
        return clientId;
    }

    /**
     * <p>Base HTTP URI of the server under test. It includes the context path, if present, and always ends with a slash</p>
     * <p>Example: {@code http://localhost:8080/a/}</p>
     *
     * @return the server's URL
     */
    public URI getUrl() {
        return config.getUrl();
    }


    /**
     * Returns the name of the user that will be used to authenticate the requests (by basic auth, if not replaced).
     *
     * @return user's name
     */
    public String getUser() {
        return config.getUser();
    }

    /**
     * Returns the password of the user that will be used to authenticate the requests (by basic auth, if not replaced).
     *
     * @return user's password
     */
    public String getPassword() {
        return config.getPassword();
    }

    /**
     * <p>Gets the full URL for a given path.</p>
     *
     * <p>The input path is considered relative to server url path ("/" or context path), even though it starts with a slash.
     * The path is relativized and appended to the {@code server url}.</p>
     *
     * <p>Note: in the case of a server url with context path - the input path should not contain the context path, otherwise
     * it will be duplicated in the resulting url</p>
     *
     * @param path the relative path
     * @return the absolute URI
     * @throws IllegalArgumentException if path cannot be parsed into an URI
     * @throws NullPointerException if path is null
     */
    public URI getUrl(String path) {
        try {
            URI pathUri = slash.relativize(new URI(path));
            return getUrl().resolve(pathUri);
        } catch (URISyntaxException e) {
            throw new IllegalArgumentException(e);
        }
    }

    /**
     * Creates a full URL for a given path with additional parameters. Same as {@link #getUrl(String)}, but adds the parameters in the URI.
     *
     * @param path path relative to server url; can start with / but should not include the server context path
     * @param parameters url parameters to be added to the url. If the given argument is {@code null}, nothing will be added to the url.
     *                   If the given argument is an empty array, it will force a "?" at the end of the url.
     * @return full url as URI
     * @throws IllegalArgumentException if path or parameters cannot be parsed into an URI
     * @throws NullPointerException if path is null
     */
    public URI getUrl(String path, List<NameValuePair> parameters) {
        // add server url and path
        URIBuilder uriBuilder = new URIBuilder(getUrl(path));
        // add parameters
        if(parameters != null) {
            uriBuilder.addParameters(parameters);
        }

        try {
            return uriBuilder.build();
        } catch (URISyntaxException e) {
            throw new IllegalArgumentException(e);
        }
    }

    /**
     * <p>Transforms an external {@code url} into a sling path, by subtracting the {@code server url} (incl. contextPath).
     * The returned path will not contain the context path, so it can be used with {@link #getUrl(String)}</p>
     *
     * <p>The url can be absolute (incl. hostname) or relative to root (starts with "/").</p>
     *
     * <p>If the server url is not a prefix of the given url, it returns the given url</p>
     *
     * <p>If the url is just a path, it returns the path (with leading slash if not already present)</p>
     *
     * @param url full url
     * @return sling path
     */
    public URI getPath(URI url) {
        // special case for urls that are server urls, but without trailing slash
        if (url.relativize(getUrl()).equals(URI.create(""))) {
            return slash;
        }

        URI contextPath = URI.create(getUrl().getPath());
        URI relativeUrl = contextPath.relativize(slash.resolve(url));

        if (relativeUrl.relativize(contextPath).equals(URI.create(""))) {
            return slash;
        }

        return slash.resolve(getUrl().relativize(relativeUrl));
    }

    /**
     * Extracts the relative sling path (to server url) from an url. Identical to {@link AbstractSlingClient#getPath(URI)},
     * except that it also parses the String int URI
     *
     * @param url string containing the full url
     * @return relative path as URI
     * @throws IllegalArgumentException if the parameter cannot be parsed
     * @throws NullPointerException if url is null
     */
    public URI getPath(String url) {
        try {
            return getPath(new URI(url));
        } catch (URISyntaxException e) {
            throw new IllegalArgumentException(e);
        }
    }

    /**
     * <p>Returns an instance of any class extending the AbstractSlingClient. The new client will
     * use the the same {@link HttpClient} and {@link SlingClientConfig} </p>
     *
     * @param clientClass the type of client requested, identified by its Class
     * @param <T>         any class extending the AbstractSlingClient
     * @return instance of a class extending the AbstractSlingClient
     * @throws ClientException if client can't be instantiated
     */
    @SuppressWarnings("unchecked")
    public <T extends AbstractSlingClient> T adaptTo(Class<T> clientClass) throws ClientException {
        T client;
        try {
            Constructor cons = clientClass.getConstructor(CloseableHttpClient.class, SlingClientConfig.class);
            client = (T) cons.newInstance(this.http, this.config);
        } catch (Exception e) {
            throw new ClientException("Could not initialize client: '" + clientClass.getCanonicalName() + "'.", e);
        }
        return client;
    }

    /**
     * Gets the value for {@code key} from the generic values
     *
     * @param key the key
     * @return the value
     */
    public String getValue(String key) {
        return this.config.getValues().get(key);
    }

    /**
     * Adds the extra {@code key, value} to the generic values
     *
     * @param key the key for witch to add a value
     * @param value the value
     */
    public void addValue(String key, String value) {
        this.config.getValues().put(key, value);
    }

    /**
     * Checks whether the handler has the given generic value
     *
     * @param key the key
     * @return true if the value was found
     */
    public boolean hasValue(String key) {
        return config.getValues().containsKey(key);
    }

    /**
     * Returns the extra values map
     *
     * @return the map of values
     */
    public Map<String, String> getValues() {
        return config.getValues();
    }

    /**
     * @return the cookie store reference
     */
    public CookieStore getCookieStore() {
        return config.getCookieStore();
    }

    /**
     * @return the credentials provider
     */
    public CredentialsProvider getCredentialsProvider() {
        return config.getCredsProvider();
    }

    //
    // HTTP convenience methods
    //

    /**
     * <p>Executes an HTTP request, WITHOUT consuming the entity in the response. The caller is responsible for consuming the entity or
     * closing the response's InputStream in order to release the connection.
     * Otherwise, the client might run out of connections and will block</p>
     *
     * <p><b>Use this with caution and only if necessary for streaming</b>, otherwise use the safe method
     * {@link #doRequest(HttpUriRequest, List, int...)}</p>
     *
     * <p>Adds the headers and checks the response against expected status</p>
     *
     * @param request the request to be executed
     * @param headers optional headers to be added to the request
     * @param expectedStatus if passed, the response status is checked against it/them, and has to match at least one of them
     * @return the response, with the entity not consumed
     * @throws ClientException if the request could not be executed
     */
    public SlingHttpResponse doStreamRequest(HttpUriRequest request, List<Header> headers, int... expectedStatus)
            throws ClientException {
        // create context from config
        HttpClientContext context = createHttpClientContextFromConfig();

        // add headers
        if (headers != null) {
            request.setHeaders(headers.toArray(new Header[headers.size()]));
        }

        try {
            log.debug("request {} {}", request.getMethod(), request.getURI());
            SlingHttpResponse response = new SlingHttpResponse(this.execute(request, context));
            log.debug("response {}", HttpUtils.getHttpStatus(response));
            // Check the status and throw a ClientException if it doesn't match expectedStatus, but close the entity before
            if (expectedStatus != null && expectedStatus.length > 0) {
                try {
                    HttpUtils.verifyHttpStatus(response, expectedStatus);
                } catch (ClientException e) {
                    // catch the exception to make sure we close the entity before re-throwing it
                    response.close();
                    throw e;
                }
            }

            return response;
        } catch (IOException e) {
            throw new ClientException("Could not execute http request", e);
        }
    }

    /**
     * <p>Executes a raw HTTP request, WITHOUT consuming the entity in the response. The caller is responsible for consuming the entity or
     * closing the response's InputStream in order to release the connection.
     * Otherwise, the client might run out of connections and will block</p>
     *
     * <p><b>Use this with caution and only if necessary for custom methods or for paths that must not be encoded</b>,
     * otherwise use the safe method {@link #doRequest(HttpUriRequest, List, int...)}</p>
     *
     * <p>It behaves as {@link #doStreamRequest(HttpUriRequest, List, int...)}, so the entity is not consumed.</p>
     * <p>Adds the headers and checks the response against expected status</p>
     *
     * @param method the request to be executed
     * @param uri the uri to be sent as it is (will not prepend the context path)
     * @param headers optional headers to be added to the request
     * @param expectedStatus if passed, the response status is checked against it/them, and has to match at least one of them
     * @return the response, with the entity not consumed
     * @throws ClientException if the request could not be executed
     */
    public SlingHttpResponse doRawRequest(String method, String uri, List<Header> headers, int... expectedStatus)
            throws ClientException {
        // create context from config
        HttpClientContext context = createHttpClientContextFromConfig();

        HttpHost host = new HttpHost(getUrl().getHost(), getUrl().getPort(), getUrl().getScheme());
        HttpRequest request = new BasicHttpRequest(method, uri);

        // add headers
        if (headers != null) {
            request.setHeaders(headers.toArray(new Header[headers.size()]));
        }

        try {
            log.debug("request {} {}", method, uri);
            SlingHttpResponse response = new SlingHttpResponse(this.execute(host, request, context));
            log.debug("response {}", HttpUtils.getHttpStatus(response));
            // Check the status and throw a ClientException if it doesn't match expectedStatus, but close the entity before
            if (expectedStatus != null && expectedStatus.length > 0) {
                try {
                    HttpUtils.verifyHttpStatus(response, expectedStatus);
                } catch (ClientException e) {
                    // catch the exception to make sure we close the entity before re-throwing it
                    response.close();
                    throw e;
                }
            }

            return response;
        } catch (IOException e) {
            throw new ClientException("Could not execute http request", e);
        }
    }

    private HttpClientContext createHttpClientContextFromConfig() {
        // create context from config
        HttpClientContext context = HttpClientContext.create();

        if (config.getCookieStore() != null) {
            context.setCookieStore(config.getCookieStore());
        }

        if (config.getCredsProvider() != null) {
            context.setCredentialsProvider(config.getCredsProvider());
        }

        if (config.getAuthCache() != null) {
            context.setAuthCache(config.getAuthCache());
        }

        return context;
    }

    /**
     * <p>Executes a GET request WITHOUT consuming the entity in the response. The caller is responsible to close the connection.
     * Otherwise, the client might run out of connections and will block</p>
     *
     * <p><b>Use this with caution and only if necessary for streaming</b>, otherwise use the safe method
     * {@link #doGet(String, List, List, int...)}</p>
     *
     * <p>Adds the given parameters and headers and checks the response against expected status</p>
     * @param requestPath path relative to client url
     * @param parameters optional url parameters to be added
     * @param headers optional headers to be added
     * @param expectedStatus if passed, the response status will have to match one of them
     * @return the response with the entity not consumed
     * @throws ClientException if the request could not be executed
     */
    public SlingHttpResponse doStreamGet(String requestPath, List<NameValuePair> parameters, List<Header> headers, int... expectedStatus)
            throws ClientException {
        // create full uri, including server url, given path and given parameters
        URI uri = getUrl(requestPath, parameters);
        // execute request
        HttpUriRequest request = new HttpGet(uri);
        return doStreamRequest(request, headers, expectedStatus);
    }

    /**
     * <p>Executes a POST request WITHOUT consuming the entity in the response. The caller is responsible to close the connection</p>
     *
     * <p><b>Use this with caution and only if necessary for streaming</b>, otherwise use the safe method
     * {@link #doPost(String, HttpEntity, List, int...)}</p>
     *
     * <p>Adds the headers and checks the response against expected status</p>
     * @param requestPath path relative to client url
     * @param entity http entity to be sent by POST
     * @param headers optional headers to be added
     * @param expectedStatus if passed, the response status will have to match one of them
     * @return the response with the entity not consumed
     * @throws ClientException if the request could not be executed
     */
    public SlingHttpResponse doStreamPost(String requestPath, HttpEntity entity, List<Header> headers, int... expectedStatus)
            throws ClientException {
        HttpEntityEnclosingRequestBase request = new HttpPost(getUrl(requestPath));
        if (entity != null) {
            request.setEntity(entity);
        }
        return doStreamRequest(request, headers, expectedStatus);
    }

    private boolean isServiceUnavailable(SlingHttpResponse response) {
        StatusLine statusLine = response.getStatusLine();
        return statusLine != null && statusLine.getStatusCode() == HttpStatus.SC_SERVICE_UNAVAILABLE;
    }


    /**
     * <p>Execute an HTTP request and consumes the entity in the response. The content is cached and can be retrieved using
     * {@code response.getContent()}.
     * This method is safe to use because it closes the entity so the caller has no responsibility.</p>
     *
     * <p>This means the response entity SHOULD NOT BE USED to read the content, e.g. {@code response.getEntity().getContent()}</p>
     *
     * @param request the request to be executed
     * @param headers optional headers to be added to the request
     * @param expectedStatus if passed, the response status will have to match one of them
     * @return the response with the entity consumed and the content cached
     * @throws ClientException if the request could not be executed
     */
    public  SlingHttpResponse doRequest(HttpUriRequest request, List<Header> headers, int... expectedStatus) throws ClientException {
        int maxRetries = Constants.HTTP_RETRIES;
        boolean needRetry = false;
        SlingHttpResponse response = null;
        do {
            try {
                if (needRetry) {
                    // add some pacing
                    Thread.sleep(Constants.HTTP_RETRIES_DELAY);
                }
                response = doStreamRequest(request, headers, expectedStatus);
                needRetry = maxRetries > 0 && isServiceUnavailable(response);
                // Consume entity and cache the content so the connection is closed
                response.getContent();
            } catch (ClientException | RuntimeException ex ) {
                needRetry = ex.getMessage().contains("Could not read content from response")
                        || ex.getMessage().contains("Instead 503 was returned!");

                if (needRetry) {
                    log.warn("Retry needed due to " + ex.getMessage());
                }
                if (maxRetries == 0) {
                    throw ex;
                }
            } catch (InterruptedException ex) {
                throw new ClientException("Interrupted while pacing request", ex);
            }
       } while (needRetry && maxRetries-- > 0);

        return response;
    }

    /**
     * <p>Executes a GET request and consumes the entity in the response (so the connection is closed immediately)
     * The content is cached and can be retrieved using {@code response.getContent()}.</p>
     *
     * <p>Adds the passed parameters and headers and checks the expected status</p>
     *
     * @param requestPath path relative to client url
     * @param parameters optional url parameters to be added
     * @param headers optional headers to be added
     * @param expectedStatus if passed, the response status will have to match one of them
     * @return the response with the entity consumed amd the content cached
     * @throws ClientException if the request could not be executed
     */
    public SlingHttpResponse doGet(String requestPath, List<NameValuePair> parameters, List<Header> headers, int... expectedStatus)
            throws ClientException {
        SlingHttpResponse response = doStreamGet(requestPath, parameters, headers, expectedStatus);

        // Consume entity and cache the content so the connection is closed
        response.getContent();

        return response;
    }

    /**
     * <p>Executes a GET request and consumes the entity in the response (so the connection is closed immediately)
     * The content is cached and can be retrieved using {@code response.getContent()}.</p>
     *
     * <p>Adds the passed parameters and checks the expected status</p>
     *
     * @param requestPath path relative to client url
     * @param parameters optional url parameters to be added
     * @param expectedStatus if passed, the response status will have to match one of them
     * @return the response with the entity consumed amd the content cached
     * @throws ClientException if the request could not be executed
     */
    public SlingHttpResponse doGet(String requestPath, List<NameValuePair> parameters, int... expectedStatus)
            throws ClientException {
        return doGet(requestPath, parameters, null, expectedStatus);
    }

    /**
     * <p>Executes a GET request and consumes the entity in the response (so the connection is closed immediately)
     * The content is cached and can be retrieved using {@code response.getContent()}.</p>
     *
     * @param requestPath path relative to client url
     * @param expectedStatus if passed, the response status will have to match one of them
     * @return the response with the entity consumed amd the content cached
     * @throws ClientException if the request could not be executed
     */
    public SlingHttpResponse doGet(String requestPath, int... expectedStatus)
            throws ClientException {
        return doGet(requestPath, null, null, expectedStatus);
    }

    /**
     * <p>Executes a HEAD request</p>
     *
     * <p>Adds the passed parameters and headers and checks the expected status</p>
     *
     * @param requestPath path relative to client url
     * @param parameters optional url parameters to be added
     * @param headers optional headers to be added
     * @param expectedStatus if passed, the response status will have to match one of them
     * @return the response
     * @throws ClientException if the request could not be executed
     */
    public SlingHttpResponse doHead(String requestPath, List<NameValuePair> parameters, List<Header> headers, int... expectedStatus)
            throws ClientException {
        HttpUriRequest request = new HttpHead(getUrl(requestPath, parameters));
        return doRequest(request, headers, expectedStatus);
    }


    /**
     * <p>Executes a POST request and consumes the entity in the response. The content is cached and be retrieved by calling
     * {@code response.getContent()}</p>
     *
     * <p>Adds the passed entity and headers and checks the expected status</p>
     *
     * @param requestPath path relative to client url
     * @param entity the entity to be added to request
     * @param headers optional headers to be added
     * @param expectedStatus if passed, the response status will have to match one of them
     * @return the response with the entity consumed and the content cached
     * @throws ClientException if the request could not be executed
     */
    public SlingHttpResponse doPost(String requestPath, HttpEntity entity, List<Header> headers, int... expectedStatus)
            throws ClientException {
        HttpEntityEnclosingRequestBase request = new HttpPost(getUrl(requestPath));
        if (entity != null) {
            request.setEntity(entity);
        }
        return doRequest(request, headers, expectedStatus);
    }

    /**
     * <p>Executes a POST request and consumes the entity in the response. The content is cached and be retrieved by calling
     * {@code response.getContent()}</p>
     *
     * <p>Adds the passed entity and checks the expected status</p>
     *
     * @param requestPath path relative to client url
     * @param entity the entity to be added to request
     * @param expectedStatus if passed, the response status will have to match one of them
     * @return the response with the entity consumed and the content cached
     * @throws ClientException if the request could not be executed
     */
    public SlingHttpResponse doPost(String requestPath, HttpEntity entity, int... expectedStatus)
            throws ClientException {
        return doPost(requestPath, entity, null, expectedStatus);
    }

    /**
     * <p>Executes a PUT request and consumes the entity in the response. The content is cached and be retrieved by calling
     * {@code response.getContent()}</p>
     *
     * <p>Adds the passed entity and headers and checks the expected status</p>
     *
     * @param requestPath path relative to client url
     * @param entity the entity to be added to request
     * @param headers optional url parameters to be added
     * @param expectedStatus if passed, the response status will have to match one of them
     * @return the response with the entity consumed and the content cached
     * @throws ClientException if the request could not be executed
     */
    public SlingHttpResponse doPut(String requestPath, HttpEntity entity, List<Header> headers, int... expectedStatus)
            throws ClientException {
        HttpEntityEnclosingRequestBase request = new HttpPut(getUrl(requestPath));
        if (entity != null) {
            request.setEntity(entity);
        }
        return doRequest(request, headers, expectedStatus);
    }

    /**
     * <p>Executes a PATCH request and consumes the entity in the response. The content is cached and be retrieved by calling
     * {@code response.getContent()}</p>
     *
     * <p>Adds the passed entity and headers and checks the expected status</p>
     *
     * @param requestPath path relative to client url
     * @param entity the entity to be added to request
     * @param headers optional url parameters to be added
     * @param expectedStatus if passed, the response status will have to match one of them
     * @return the response with the entity consumed and the content cached
     * @throws ClientException if the request could not be executed
     */
    public SlingHttpResponse doPatch(String requestPath, HttpEntity entity, List<Header> headers, int... expectedStatus)
            throws ClientException {
        HttpEntityEnclosingRequestBase request = new HttpPatch(getUrl(requestPath));
        if (entity != null) {
            request.setEntity(entity);
        }
        return doRequest(request, headers, expectedStatus);
    }

    /**
     * <p>Executes a DELETE request and consumes the entity in the response. The content is cached and be retrieved by calling
     * {@code response.getContent()}</p>
     *
     * <p>Adds the passed parameters and headers and checks the expected status</p>
     *
     * @param requestPath path relative to client url
     * @param parameters optional url parameters to be added
     * @param headers optional url parameters to be added
     * @param expectedStatus if passed, the response status will have to match one of them
     * @return the response with the entity consumed and the content cached
     * @throws ClientException if the request could not be executed
     */
    public SlingHttpResponse doDelete(String requestPath, List<NameValuePair> parameters, List<Header> headers, int... expectedStatus)
            throws ClientException {
        HttpUriRequest request = new HttpDelete(getUrl(requestPath, parameters));
        return doRequest(request, headers, expectedStatus);
    }

    @Override
    /**
     * <p>Closes the http client and makes sure all the underlying resources, like the connection manager, shut down </p>
     *
     */
    public void close() throws IOException {
        this.http.close();
    }


    //
    // HttpClient  base methods
    //

    @Deprecated
    @SuppressWarnings("deprecation")
    public org.apache.http.params.HttpParams getParams() {
        return this.http.getParams();
    }

    @Deprecated
    @SuppressWarnings("deprecation")
    public org.apache.http.conn.ClientConnectionManager getConnectionManager() {
        return this.http.getConnectionManager();
    }

    @SuppressWarnings("DuplicateThrows")
    public HttpResponse execute(HttpUriRequest request) throws IOException, ClientProtocolException {
        return this.http.execute(request);
    }

    // maybe throw UnsupportedMethodException
    @SuppressWarnings("DuplicateThrows")
    public CloseableHttpResponse execute(HttpUriRequest request, HttpContext context)
            throws IOException, ClientProtocolException {
        return this.http.execute(request, context);
    }

    @SuppressWarnings("DuplicateThrows")
    public HttpResponse execute(HttpHost target, HttpRequest request)
            throws IOException, ClientProtocolException {
        return this.http.execute(target, request);
    }

    @SuppressWarnings("DuplicateThrows")
    public CloseableHttpResponse execute(HttpHost target, HttpRequest request, HttpContext context)
            throws IOException, ClientProtocolException {
        return this.http.execute(target, request, context);
    }

    @SuppressWarnings("DuplicateThrows")
    public <T> T execute(HttpUriRequest request, ResponseHandler<? extends T> responseHandler)
            throws IOException, ClientProtocolException {
        return this.http.execute(request, responseHandler);
    }

    @SuppressWarnings("DuplicateThrows")
    public <T> T execute(HttpUriRequest request, ResponseHandler<? extends T> responseHandler, HttpContext context)
            throws IOException, ClientProtocolException {
        return this.http.execute(request, responseHandler, context);
    }

    @SuppressWarnings("DuplicateThrows")
    public <T> T execute(HttpHost target, HttpRequest request, ResponseHandler<? extends T> responseHandler)
            throws IOException, ClientProtocolException {
        return this.http.execute(target, request, responseHandler);
    }

    @SuppressWarnings("DuplicateThrows")
    public <T> T execute(HttpHost target, HttpRequest request, ResponseHandler<? extends T> responseHandler, HttpContext context)
            throws IOException, ClientProtocolException {
        return this.http.execute(target, request, responseHandler, context);
    }
}
