com.redhat.red.build.koji.http.httpclient4.HC4SyncObjectClient.java Source code

Java tutorial

Introduction

Here is the source code for com.redhat.red.build.koji.http.httpclient4.HC4SyncObjectClient.java

Source

/**
 * Copyright (C) 2015 Red Hat, Inc. (jcasey@redhat.com)
 *
 * 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.redhat.red.build.koji.http.httpclient4;

import com.codahale.metrics.MetricRegistry;
import com.codahale.metrics.Timer;
import com.redhat.red.build.koji.model.xmlrpc.messages.VoidResponse;
import org.apache.commons.io.IOUtils;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.commonjava.rwx.anno.Request;
import org.commonjava.rwx.api.RWXMapper;
import org.commonjava.rwx.error.XmlRpcException;
import com.redhat.red.build.koji.http.RequestModifier;
import com.redhat.red.build.koji.http.UrlBuildResult;
import com.redhat.red.build.koji.http.UrlBuilder;
import com.redhat.red.build.koji.http.error.XmlRpcTransportException;
import org.commonjava.util.jhttpc.HttpFactory;
import org.commonjava.util.jhttpc.JHttpCException;
import org.commonjava.util.jhttpc.model.SiteConfig;
import org.commonjava.util.jhttpc.util.UrlUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.MalformedURLException;
import java.util.Arrays;

import static com.codahale.metrics.MetricRegistry.name;

public class HC4SyncObjectClient {
    private final HttpFactory httpFactory;

    private final SiteConfig siteConfig;

    private final MetricRegistry metricRegistry;

    private final String[] extraPath;

    public HC4SyncObjectClient(final HttpFactory httpFactory, final SiteConfig siteConfig,
            final MetricRegistry metricRegistry, String... extraPath) {
        this.httpFactory = httpFactory;
        this.siteConfig = siteConfig;
        this.metricRegistry = metricRegistry;
        this.extraPath = extraPath;
    }

    public <T> T call(final Object request, final Class<T> responseType, final UrlBuilder urlBuilder,
            final RequestModifier requestModifier) throws XmlRpcException {
        if (metricRegistry == null) {
            return doCall(request, responseType, urlBuilder, requestModifier);
        }

        // Apply global and per request metric

        final Timer.Context timerContext = metricRegistry.timer(name(getClass(), "call")).time();
        final Timer.Context requestTimerContext = metricRegistry.timer(name(request.getClass(), "call")).time();
        try {
            return doCall(request, responseType, urlBuilder, requestModifier);
        } finally {
            timerContext.stop();
            requestTimerContext.stop();
        }
    }

    private <T> T doCall(final Object request, final Class<T> responseType, final UrlBuilder urlBuilder,
            final RequestModifier requestModifier) throws XmlRpcException {
        final String methodName = getRequestMethod(request);
        if (methodName == null) {
            throw new XmlRpcTransportException("Request value is not annotated with @Request.", request);
        }

        final HttpPost method;
        try {
            Logger logger = LoggerFactory.getLogger(getClass());

            String url = UrlUtils.buildUrl(siteConfig.getUri(), extraPath);
            logger.trace("Unadorned URL: '{}'", url);

            if (urlBuilder != null) {
                UrlBuildResult buildResult = urlBuilder.buildUrl(url);
                logger.trace("UrlBuilder ({}) result: {}", urlBuilder.getClass().getName(), buildResult);
                url = buildResult.throwError().get();
            }
            logger.trace("POSTing {} request to: '{}'", methodName, url);

            method = new HttpPost(url);
            method.setHeader("Content-Type", "text/xml");

            if (requestModifier != null) {
                requestModifier.modifyRequest(method);
            }

            final String content = new RWXMapper().render(request);
            logger.trace("Sending request:\n\n" + content + "\n\n");

            method.setEntity(new StringEntity(content));
        } catch (final UnsupportedEncodingException e) {
            throw new XmlRpcTransportException("Call failed: " + methodName, request, e);
        } catch (MalformedURLException e) {
            throw new XmlRpcTransportException("Failed to construct URL from: %s and extra-path: %s. Reason: %s", e,
                    siteConfig.getUri(), Arrays.asList(extraPath), e.getMessage());
        }

        CloseableHttpClient client = null;
        try {
            client = httpFactory.createClient(siteConfig);

            if (Void.class.equals(responseType)) {
                final ObjectResponseHandler<VoidResponse> handler = new ObjectResponseHandler<VoidResponse>(
                        VoidResponse.class);
                client.execute(method, handler);

                handler.throwExceptions();
                return null;
            } else {
                final ObjectResponseHandler<T> handler = new ObjectResponseHandler<T>(responseType);
                final T response = client.execute(method, handler);

                handler.throwExceptions();
                return response;

            }
        } catch (final ClientProtocolException e) {
            throw new XmlRpcTransportException("Call failed: " + methodName, request, e);
        } catch (final IOException e) {
            throw new XmlRpcTransportException("Call failed: " + methodName, request, e);
        } catch (JHttpCException e) {
            throw new XmlRpcTransportException("Call failed: " + methodName, request, e);
        } finally {
            IOUtils.closeQuietly(client);
        }
    }

    private String getRequestMethod(Object obj) {
        final Class<?> type = ((obj instanceof Class<?>) ? (Class<?>) obj : obj.getClass());
        final Request req = type.getAnnotation(Request.class);
        if (req != null) {
            return req.method();
        }
        return null;
    }

    public void close() {
        IOUtils.closeQuietly(httpFactory);
    }
}