io.soabase.client.apache.WrappedHttpClient.java Source code

Java tutorial

Introduction

Here is the source code for io.soabase.client.apache.WrappedHttpClient.java

Source

/**
 * Copyright 2014 Jordan Zimmerman
 *
 * 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 io.soabase.client.apache;

import io.soabase.core.features.client.ClientUtils;
import io.soabase.core.features.client.RetryComponents;
import io.soabase.core.features.client.RetryContext;
import io.soabase.core.features.discovery.SoaDiscovery;
import io.soabase.core.features.discovery.SoaDiscoveryInstance;
import io.soabase.core.features.client.SoaRequestId;
import org.apache.http.HttpEntity;
import org.apache.http.HttpHost;
import org.apache.http.HttpRequest;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.ResponseHandler;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.conn.ClientConnectionManager;
import org.apache.http.params.HttpParams;
import org.apache.http.protocol.HttpContext;
import org.apache.http.util.Args;
import org.apache.http.util.EntityUtils;
import java.io.IOException;
import java.lang.reflect.UndeclaredThrowableException;
import java.net.URI;
import java.net.URISyntaxException;

@SuppressWarnings("deprecation")
public class WrappedHttpClient implements HttpClient {
    private final HttpClient implementation;
    private final SoaDiscovery discovery;
    private final RetryComponents retryComponents;

    public WrappedHttpClient(HttpClient implementation, SoaDiscovery discovery, RetryComponents retryComponents) {
        this.implementation = implementation;
        this.discovery = discovery;
        this.retryComponents = retryComponents;
    }

    @Override
    public HttpParams getParams() {
        return implementation.getParams();
    }

    @Override
    public ClientConnectionManager getConnectionManager() {
        return implementation.getConnectionManager();
    }

    @Override
    public HttpResponse execute(HttpUriRequest request) throws IOException {
        return execute(request, (HttpContext) null);
    }

    @Override
    public HttpResponse execute(HttpUriRequest request, HttpContext context) throws IOException {
        addRequestId(request);

        RetryContext retryContext = new RetryContext(retryComponents, request.getURI(), request.getMethod());
        for (int retryCount = 0; /* no check */; ++retryCount) {
            SoaDiscoveryInstance instance = ClientUtils.hostToInstance(discovery, retryContext.getOriginalHost());
            retryContext.setInstance(instance);

            URI filteredUri = ClientUtils.filterUri(request.getURI(), instance);
            if (filteredUri != null) {
                request = new WrappedHttpUriRequest(request, filteredUri);
            }
            try {
                HttpResponse response = implementation.execute(request, context);
                if (!retryContext.shouldBeRetried(retryCount, response.getStatusLine().getStatusCode(), null)) {
                    return response;
                }
            } catch (IOException e) {
                if (!retryContext.shouldBeRetried(retryCount, 0, e)) {
                    throw e;
                }
            }
        }
    }

    @Override
    public HttpResponse execute(HttpHost target, HttpRequest request) throws IOException {
        return execute(target, request, (HttpContext) null);
    }

    @Override
    public HttpResponse execute(HttpHost target, HttpRequest request, HttpContext context) throws IOException {
        addRequestId(request);

        URI uri;
        try {
            uri = new URI(request.getRequestLine().getUri());
        } catch (URISyntaxException e) {
            // TODO logging
            throw new IOException(e);
        }

        RetryContext retryContext = new RetryContext(retryComponents, uri, request.getRequestLine().getMethod());
        for (int retryCount = 0; /* no check */; ++retryCount) {
            try {
                SoaDiscoveryInstance instance = ClientUtils.hostToInstance(discovery,
                        retryContext.getOriginalHost());
                retryContext.setInstance(instance);

                URI filteredUri = ClientUtils.filterUri(uri, instance);
                if (filteredUri != null) {
                    target = toHost(filteredUri);
                    request = new WrappedHttpRequest(request, filteredUri);
                }
                HttpResponse response = implementation.execute(target, request, context);
                if (!retryContext.shouldBeRetried(retryCount, response.getStatusLine().getStatusCode(), null)) {
                    return response;
                }
            } catch (IOException e) {
                if (!retryContext.shouldBeRetried(retryCount, 0, e)) {
                    throw e;
                }
            }
        }
    }

    @Override
    public <T> T execute(HttpUriRequest request, ResponseHandler<? extends T> responseHandler) throws IOException {
        return internalExecute(request, null, null, responseHandler, null);
    }

    @Override
    public <T> T execute(HttpUriRequest request, ResponseHandler<? extends T> responseHandler, HttpContext context)
            throws IOException {
        return internalExecute(request, null, null, responseHandler, context);
    }

    @Override
    public <T> T execute(HttpHost target, HttpRequest request, ResponseHandler<? extends T> responseHandler)
            throws IOException {
        return internalExecute(null, target, request, responseHandler, null);
    }

    @Override
    public <T> T execute(HttpHost target, HttpRequest request, ResponseHandler<? extends T> responseHandler,
            HttpContext context) throws IOException {
        return internalExecute(null, target, request, responseHandler, context);
    }

    private void addRequestId(HttpRequest request) {
        SoaRequestId.HeaderSetter<HttpRequest> setter = new SoaRequestId.HeaderSetter<HttpRequest>() {
            @Override
            public void setHeader(HttpRequest request, String header, String value) {
                request.addHeader(header, value);
            }
        };
        SoaRequestId.checkSetHeaders(request, setter);
    }

    private HttpHost toHost(URI uri) {
        return new HttpHost(uri.getHost(), uri.getPort(), uri.getScheme());
    }

    // mostly copied from CloseableHttpClient.execute()
    private <T> T internalExecute(final HttpUriRequest uriRequest, final HttpHost target, final HttpRequest request,
            final ResponseHandler<? extends T> responseHandler, final HttpContext context) throws IOException {
        Args.notNull(responseHandler, "Response handler");

        final HttpResponse response = (uriRequest != null) ? execute(uriRequest, context)
                : execute(target, request, context);

        final T result;
        try {
            result = responseHandler.handleResponse(response);
        } catch (final Exception t) {
            final HttpEntity entity = response.getEntity();
            try {
                EntityUtils.consume(entity);
            } catch (final Exception t2) {
                // Log this exception. The original exception is more
                // important and will be thrown to the caller.
                // TODO this.log.warn("Error consuming content after an exception.", t2);
            }
            if (t instanceof RuntimeException) {
                throw (RuntimeException) t;
            }
            if (t instanceof IOException) {
                throw (IOException) t;
            }
            throw new UndeclaredThrowableException(t);
        }

        // Handling the response was successful. Ensure that the content has
        // been fully consumed.
        final HttpEntity entity = response.getEntity();
        EntityUtils.consume(entity);
        return result;
    }
}