All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.comcast.drivethru.client.DefaultRestClient Maven / Gradle / Ivy

There is a newer version: 2.0.7
Show newest version
/**
 * Copyright 2013 Comcast Cable Communications Management, LLC
 *
 * 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.comcast.drivethru.client;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;

import org.apache.commons.io.IOUtils;
import org.apache.http.HttpEntity;
import org.apache.http.HttpEntityEnclosingRequest;
import org.apache.http.HttpStatus;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.HttpResponseException;
import org.apache.http.client.methods.HttpRequestBase;
import org.apache.http.client.utils.HttpClientUtils;
import org.apache.http.config.SocketConfig;
import org.apache.http.entity.ByteArrayEntity;
import org.apache.http.impl.client.HttpClientBuilder;

import com.comcast.drivethru.RestClient;
import com.comcast.drivethru.exception.HttpException;
import com.comcast.drivethru.exception.HttpStatusException;
import com.comcast.drivethru.security.SecurityProvider;
import com.comcast.drivethru.transform.JsonTransformer;
import com.comcast.drivethru.transform.Transformer;
import com.comcast.drivethru.utils.Method;
import com.comcast.drivethru.utils.RestRequest;
import com.comcast.drivethru.utils.RestResponse;
import com.comcast.drivethru.utils.URL;

/**
 * The default implementation of a {@link RestClient}.
 *
 * @author Clark Malmgren
 * @author Kevin Pearson
 */
public class DefaultRestClient implements RestClient {

    private String defaultBaseUrl;
    private Transformer transformer;
    private HttpClient delegate;
    private SecurityProvider securityProvider;
    private Map defaultHeaders;

    /**
     * Constructs a new {@link DefaultRestClient} with no defaultBaseUrl that will use
     * the the standard {@link JsonTransformer} and a default {@link HttpClient} with a default
     * timeout of 10 seconds ({@link RestClient#DEFAULT_TIMEOUT}).
     * 

* Because no defaultBaseUrl has been defined, all executions must provide fully * defined {@link URL}s or they will fail. Use of this constructor is discouraged. *

*/ public DefaultRestClient() { this(null); } private static HttpClient defaultClient() { return HttpClientBuilder.create().setDefaultSocketConfig(SocketConfig.custom().setSoTimeout(DEFAULT_TIMEOUT).build()).build(); } /** * Constructs a new {@link DefaultRestClient} with the given defaultBaseUrl that * will use the the standard {@link JsonTransformer} and a default {@link HttpClient} with a * default timeout of 10 seconds ({@link RestClient#DEFAULT_TIMEOUT}). * * @param defaultBaseUrl * the default base URL used for this connection */ public DefaultRestClient(String defaultBaseUrl) { this(defaultBaseUrl, new JsonTransformer()); } /** * Constructs a new {@link DefaultRestClient} with the given defaultBaseUrl that * will use the given {@link Transformer} and a default {@link HttpClient} with a default * timeout of 10 seconds ({@link RestClient#DEFAULT_TIMEOUT}). * * @param defaultBaseUrl * the default base URL used for this connection * @param transformer * the transformer for handling serialization of HTTP body contents */ public DefaultRestClient(String defaultBaseUrl, Transformer transformer) { this(defaultBaseUrl, transformer, defaultClient()); } /** * Constructs a new {@link DefaultRestClient} with the given defaultBaseUrl that * will use the given {@link HttpClient} and the standard {@link JsonTransformer}. * * @param defaultBaseUrl * the default base URL used for this connection * @param delegate * the inner HTTP connection component */ public DefaultRestClient(String defaultBaseUrl, HttpClient delegate) { this(defaultBaseUrl, new JsonTransformer(), delegate); } /** * Constructs a new {@link DefaultRestClient} with the given defaultBaseUrl that * will use the given {@link Transformer} and {@link HttpClient}. * * @param defaultBaseUrl * the default base URL used for this connection * @param transformer * the transformer for handling serialization of HTTP body contents * @param delegate * the inner HTTP connection component */ public DefaultRestClient(String defaultBaseUrl, Transformer transformer, HttpClient delegate) { this.defaultBaseUrl = defaultBaseUrl; this.transformer = transformer; this.delegate = delegate; this.securityProvider = null; this.defaultHeaders = new HashMap<>(); } /* * (non-Javadoc) * @see com.comcast.tvx.megahttp.RestClient#getDefaultBaseUrl() */ @Override public String getDefaultBaseUrl() { return defaultBaseUrl; } /* * (non-Javadoc) * @see com.comcast.tvx.megahttp.clients.BasicMegaHttpClient#addDefaultHeader(java.lang.String, * java.lang.String) */ @Override public void addDefaultHeader(String name, String value) { this.defaultHeaders.put(name, value); } /* * (non-Javadoc) * @see * com.comcast.tvx.megahttp.clients.BasicMegaHttpClient#setSecurityProvider(com.comcast.tvx. * megahttp.security.SecurityProvider) */ @Override public void setSecurityProvider(SecurityProvider securityProvider) { this.securityProvider = securityProvider; } /* * (non-Javadoc) * @see * com.comcast.tvx.megahttp.RestClient#setTransformer(com.comcast.tvx.megahttp.rest.Transformer * ) */ @Override public void setTransformer(Transformer transformer) { this.transformer = transformer; } /* * (non-Javadoc) * @see * com.comcast.tvx.megahttp.clients.BasicMegaHttpClient#execute(com.comcast.tvx.megahttp.HttpRequest * ) */ @Override public RestResponse execute(RestRequest request) throws HttpException { /* Build the URL String */ String url = request.getUrl().setDefaultBaseUrl(defaultBaseUrl).build(); /* Get our Apache RestRequest object */ Method method = request.getMethod(); HttpRequestBase req = method.getRequest(url); req.setConfig(request.getConfig()); /* Add the Body */ byte[] payload = request.getBody(); if (null != payload) { if (req instanceof HttpEntityEnclosingRequest) { HttpEntity entity = new ByteArrayEntity(payload); ((HttpEntityEnclosingRequest) req).setEntity(entity); } else { throw new HttpException("Cannot attach a body to a " + method.name() + " request"); } } /* Add all Headers */ for (Entry pair : defaultHeaders.entrySet()) { req.addHeader(pair.getKey(), pair.getValue()); } for (Entry pair : request.getHeaders().entrySet()) { req.addHeader(pair.getKey(), pair.getValue()); } /* If there is a security provider, sign */ if (null != securityProvider) { securityProvider.sign(req); } /* Closed in the finally block */ InputStream in = null; ByteArrayOutputStream baos = null; try { /* Finally, execute the thing */ org.apache.http.HttpResponse resp = delegate.execute(req); /* Create our response */ RestResponse response = new RestResponse(resp.getStatusLine()); /* Add all Headers */ response.addAll(resp.getAllHeaders()); /* Add the content */ HttpEntity body = resp.getEntity(); if (null != body) { in = body.getContent(); baos = new ByteArrayOutputStream(); IOUtils.copy(in, baos); response.setBody(baos.toByteArray()); } return response; } catch (RuntimeException ex) { // release resources immediately req.abort(); throw ex; } catch (HttpResponseException hrex) { throw new HttpStatusException(hrex.getStatusCode()); } catch (ClientProtocolException cpex) { throw new HttpException("HTTP Protocol error occurred.", cpex); } catch (IOException ioex) { throw new HttpException("Error establishing connection.", ioex); } finally { req.abort(); IOUtils.closeQuietly(in); IOUtils.closeQuietly(baos); } } /* * (non-Javadoc) * @see com.comcast.tvx.megahttp.clients.EasyMegaHttpClient#get(java.lang.String, * java.lang.Class) */ @Override public T get(String path, Class type) throws HttpException { return this.get(new URL().setPath(path), type); } /* * (non-Javadoc) * @see * com.comcast.tvx.megahttp.clients.EasyMegaHttpClient#get(com.comcast.tvx.megahttp.utils.URL, * java.lang.Class) */ @Override public T get(URL url, Class type) throws HttpException { RestRequest request = new RestRequest(url, Method.GET); RestResponse response = execute(request); if (response.getStatusCode() != HttpStatus.SC_OK) { throw new HttpStatusException(response.getStatusCode(), response.getStatusMessage()); } else { String contentType = response.getContentType(); if ((contentType != null) && contentType.equals(transformer.getMime())) { byte[] body = response.getBody(); return transformer.read(body, type); } else { throw new HttpException("Invalid Content Type: " + contentType); } } } /* * (non-Javadoc) * @see com.comcast.tvx.megahttp.clients.EasyMegaHttpClient#put(java.lang.String, T) */ @Override public boolean put(String path, T t) throws HttpException { return this.put(new URL().setPath(path), t); } /* * (non-Javadoc) * @see * com.comcast.tvx.megahttp.clients.EasyMegaHttpClient#put(com.comcast.tvx.megahttp.utils.URL, * T) */ @Override public boolean put(URL url, T t) throws HttpException { RestRequest request = new RestRequest(url, Method.PUT); request.setContentType(transformer.getMime()); request.setBody(transformer.write(t)); RestResponse response = execute(request); switch (response.getStatusCode()) { case HttpStatus.SC_CREATED: return true; case HttpStatus.SC_OK: case HttpStatus.SC_NO_CONTENT: return false; default: throw new HttpStatusException(response.getStatusCode(), response.getStatusMessage()); } } /* * (non-Javadoc) * @see com.comcast.tvx.megahttp.clients.EasyMegaHttpClient#delete(java.lang.String) */ @Override public boolean delete(String path) throws HttpException { return this.delete(new URL().setPath(path)); } /* * (non-Javadoc) * @see * com.comcast.tvx.megahttp.clients.EasyHttpClient#delete(com.comcast.tvx.megahttp.utils.URL) */ @Override public boolean delete(URL url) throws HttpException { RestRequest request = new RestRequest(url, Method.DELETE); RestResponse response = execute(request); switch (response.getStatusCode()) { case HttpStatus.SC_OK: return true; case HttpStatus.SC_ACCEPTED: case HttpStatus.SC_NO_CONTENT: return false; default: throw new HttpStatusException(response.getStatusCode(), response.getStatusMessage()); } } /* * (non-Javadoc) * @see com.comcast.tvx.megahttp.RestClient#post(java.lang.String, java.lang.Class) */ @Override public T post(String path, Class responseType) throws HttpException { return post(path, null, responseType); } /* * (non-Javadoc) * @see com.comcast.tvx.megahttp.RestClient#post(java.lang.String, java.lang.Class) */ @Override public T post(URL url, Class responseType) throws HttpException { return post(url, null, responseType); } /* * (non-Javadoc) * @see com.comcast.tvx.megahttp.RestClient#post(java.lang.String, java.lang.Object, * java.lang.Class) */ @Override public T post(String path, P payload, Class responseType) throws HttpException { return this.post(new URL().setPath(path), payload, responseType); } /* * (non-Javadoc) * @see com.comcast.tvx.megahttp.RestClient#post(com.comcast.tvx.megahttp.utils.URL, * java.lang.Object, java.lang.Class) */ @Override public T post(URL url, P payload, Class responseType) throws HttpException { RestRequest request = new RestRequest(url, Method.POST); if (null != payload) { request.setContentType(transformer.getMime()); request.setBody(transformer.write(payload)); } RestResponse response = execute(request); /* Handle required status codes as per http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html */ switch (response.getStatusCode()) { case HttpStatus.SC_OK: case HttpStatus.SC_CREATED: case HttpStatus.SC_NO_CONTENT: break; default: throw new HttpStatusException(response.getStatusCode(), response.getStatusMessage()); } /* Read data if the Content-Type was correct */ if (responseType.equals(void.class)) { return null; } else { String contentType = response.getContentType(); if ((contentType != null) && contentType.equals(transformer.getMime())) { byte[] body = response.getBody(); return transformer.read(body, responseType); } else { throw new HttpException("Invalid Content Type: " + contentType); } } } /* * (non-Javadoc) * @see java.io.Closeable#close() */ @Override public void close() throws IOException { HttpClientUtils.closeQuietly(delegate); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy