/** * */ package com.ebay.cloud.cms.typsafe.restful; import java.net.InetAddress; import java.net.UnknownHostException; import java.text.MessageFormat; import java.util.Date; import java.util.HashMap; import java.util.Map; import java.util.Map.Entry; import javax.ws.rs.core.MultivaluedMap; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.ebay.cloud.cms.typsafe.entity.ICMSEntity; import com.ebay.cloud.cms.typsafe.exception.CMSClientException; import com.ebay.cloud.cms.typsafe.service.CMSClientConfig; import com.ebay.cloud.cms.typsafe.service.CMSClientContext; import com.sun.jersey.api.client.Client; import com.sun.jersey.api.client.ClientResponse; import com.sun.jersey.api.client.WebResource; import com.sun.jersey.core.util.StringKeyStringValueIgnoreCaseMultivaluedMap; /** * @author liasu * */ public class RestExecutor { private static final Logger logger = LoggerFactory.getLogger(RestExecutor.class); private static final String CORRELATION_ID_HEADER = "X-EVENT_TRACKER_CORRELATIONID"; private static final String CORRELATION_ID_PATTERN = "{0}-{1}-{2}-{3}"; public static enum HttpRequest { GET, POST, PUT, DELETE } private final String fullUrl; private final Object entity; private final Client restClient; private final HttpRequest request; private final CMSClientConfig config; private final Map<String, String> queryParams; private final Map<String, String> headers; private final IJsonBuilder builder; private final CMSClientContext context; public RestExecutor(CMSClientConfig config, Client restClient, HttpRequest request, Object entity, String url, Map<String, String> queryParams, Map<String, String> headers, CMSClientContext context) { this(config, restClient, request, entity, url, queryParams, headers, (IJsonBuilder) null, context); } public RestExecutor(CMSClientConfig config, Client restClient, HttpRequest request, Object entity, String url, Map<String, String> queryParams, Map<String, String> headers, IJsonBuilder builder, CMSClientContext context) { this.config = config; this.restClient = restClient; this.request = request; this.entity = entity; this.fullUrl = url; this.context = context; this.queryParams = new HashMap<String, String>(); this.headers = new HashMap<String, String>(); if (queryParams != null) { this.queryParams.putAll(queryParams); } if (headers != null) { this.headers.putAll(headers); } if (builder == null) { this.builder = new JsonBuilder(this.config); } else { this.builder = builder; } } public ClientResponse build() { String json = null; // rest standards recommends that get doesn't rely on the // request body if (entity != null && (request == HttpRequest.POST || request == HttpRequest.PUT)) { json = toJson(entity); } WebResource.Builder builder = buildResource(json); // store the request to context if (context != null) { context.setLastRequest(new CMSClientContext.RequestInfo(request, fullUrl, json)); } logger.debug(MessageFormat.format("Sending request, with method: {0} base url: {1}. Payload: {2}\n", request.name(), fullUrl, json)); long last = System.nanoTime(); ClientResponse cr = null; try { cr = builder.method(request.name(), ClientResponse.class); } catch (Exception e) { throw new CMSClientException(-1, "Request got exception! : " + e.getMessage() + " url is: " + fullUrl + " endpoint: " + config.getServerBaseUrl(), e, e.getMessage(), context.getLastRequest()); } logger.debug(MessageFormat.format("Got server response, method: {0} base url: {1}. Payload: {2}\n. Used time: {3}(ns).", request.name(), fullUrl, json, (System.nanoTime() - last))); return cr; } private WebResource.Builder buildResource(String json) { WebResource resource = restClient.resource(fullUrl); MultivaluedMap<String, String> queryParamMap = new StringKeyStringValueIgnoreCaseMultivaluedMap(); for (Entry<String, String> e : queryParams.entrySet()) { queryParamMap.add(e.getKey(), e.getValue()); } resource = resource.queryParams(queryParamMap); // add correlation id String correlation = generateCorrelationId(); WebResource.Builder builder = resource.header("Content-Type", "application/json").header("Accept", "application/json"); for (Entry<String, String> e : headers.entrySet()) { builder.header(e.getKey(), e.getValue()); } if (json != null) { builder.entity(json); if (config.isUseGzip()) { builder.header("Content-Encoding", "gzip"); } } if (config.isUseGzip()) { builder.header("Accept-Encoding", "gzip"); } builder.header(CORRELATION_ID_HEADER, correlation); return builder; } protected String toJson(Object object) { return builder.buildJson(object); } private String generateCorrelationId() { String ip = "0.0.0.0";// NON-SONAR try { ip = InetAddress.getLocalHost().getHostName(); } catch (UnknownHostException uhe) { logger.error("UnknowHostException when try to ip address, set as unknown!", uhe); } long timestamp = new Date().getTime(); String user = config.getUser() == null ? "unknowUser" : config.getUser(); String oid = ""; if (entity instanceof ICMSEntity) { oid = ((ICMSEntity) entity).get_id(); } return MessageFormat.format(CORRELATION_ID_PATTERN, ip, timestamp, user, oid); } }