Divide the MSB source codes into two repos
[msb/apigateway.git] / apiroute / apiroute-service / src / main / java / org / onap / msb / apiroute / wrapper / consulextend / util / Http.java
1 package org.onap.msb.apiroute.wrapper.consulextend.util;
2
3 import java.io.IOException;
4 import java.lang.reflect.ParameterizedType;
5 import java.lang.reflect.Type;
6 import java.math.BigInteger;
7 import java.util.List;
8 import java.util.Map;
9
10 import org.apache.commons.io.IOUtils;
11 import org.apache.http.HttpEntity;
12 import org.apache.http.HttpResponse;
13 import org.apache.http.client.methods.HttpGet;
14 import org.apache.http.concurrent.FutureCallback;
15 import org.apache.http.impl.nio.client.CloseableHttpAsyncClient;
16 import org.apache.http.impl.nio.client.HttpAsyncClients;
17 import org.eclipse.jetty.http.HttpStatus;
18 import org.onap.msb.apiroute.wrapper.consulextend.async.ConsulResponseCallback;
19 import org.onap.msb.apiroute.wrapper.consulextend.async.ConsulResponseHeader;
20 import org.onap.msb.apiroute.wrapper.consulextend.async.OriginalConsulResponse;
21 import org.slf4j.Logger;
22 import org.slf4j.LoggerFactory;
23
24 import com.fasterxml.jackson.core.type.TypeReference;
25 import com.google.common.collect.ImmutableList;
26 import com.google.common.collect.ImmutableMap;
27 import com.google.common.collect.Sets;
28 import com.orbitz.consul.ConsulException;
29 import com.orbitz.consul.model.ConsulResponse;
30 import com.orbitz.consul.option.CatalogOptions;
31 import com.orbitz.consul.option.QueryOptions;
32 import com.orbitz.consul.util.Jackson;
33
34 public class Http {
35         private static final Logger LOGGER = LoggerFactory.getLogger(Http.class);
36
37         private final static CloseableHttpAsyncClient httpAsyncClient = HttpAsyncClients
38                         .custom().setMaxConnTotal(Integer.MAX_VALUE)
39                         .setMaxConnPerRoute(Integer.MAX_VALUE).build();
40
41         private static Http instance = null;
42
43         private Http() {
44         }
45
46         public static Http getInstance() {
47                 if (instance == null) {
48                         instance = new Http();
49                         httpAsyncClient.start();
50                 }
51
52                 return instance;
53         }
54
55         // async get data from consul,and handle response immediately
56         public <T> void asyncGet(String requestURI,
57                         final TypeReference<T> responseType,
58                         final ConsulResponseCallback<T> callback, final Integer... okCodes) {
59                 // LOGGER.info("Async request:"+requestURI);
60
61                 httpAsyncClient.execute(new HttpGet(requestURI),
62                                 new FutureCallback<HttpResponse>() {
63
64                                         public void completed(final HttpResponse response) {
65                                                 callback.onComplete(consulResponse(responseType,
66                                                                 response));
67                                         }
68
69                                         public void failed(final Exception ex) {
70                                                 callback.onFailure(ex);
71                                         }
72
73                                         public void cancelled() {
74                                                 LOGGER.warn("cancelled async request");
75                                         }
76                                 });
77         }
78
79         // async get data from consul,and handle response delay
80         public <T> void asyncGetDelayHandle(String requestURI,
81                         final TypeReference<T> responseType,
82                         final ConsulResponseCallback<T> callback, final Integer... okCodes) {
83
84                 httpAsyncClient.execute(new HttpGet(requestURI),
85                                 new FutureCallback<HttpResponse>() {
86
87                                         public void completed(final HttpResponse response) {
88                                                 OriginalConsulResponse<T> originalConsulResponse = new OriginalConsulResponse<T>(
89                                                                 response, responseType);
90                                                 
91                                                 //handle not 2xx code
92                                                 if (!isSuccessful(response)) {
93                                                         
94                                                         LOGGER.warn("response statuscode:"
95                                                                         + response.getStatusLine().getStatusCode());
96                                                         
97                                                         callback.onFailure(new ConsulException(
98                                                                         "response statuscode:"
99                                                                                         + response.getStatusLine()
100                                                                                                         .getStatusCode()));
101                                                 } else {
102                                                         callback.onDelayComplete(originalConsulResponse);
103                                                 }
104
105                                         }
106
107                                         public void failed(final Exception ex) {
108                                                 callback.onFailure(ex);
109                                         }
110
111                                         public void cancelled() {
112                                                 LOGGER.warn("cancelled async request");
113                                         }
114                                 });
115         }
116
117         public static ConsulResponseHeader consulResponseHeader(
118                         HttpResponse response) {
119                 String indexHeaderValue = response.getFirstHeader("X-Consul-Index")
120                                 .getValue();
121                 String lastContactHeaderValue = response.getFirstHeader(
122                                 "X-Consul-Lastcontact").getValue();
123                 String knownLeaderHeaderValue = response.getFirstHeader(
124                                 "X-Consul-Knownleader").getValue();
125
126                 BigInteger index = indexHeaderValue == null ? new BigInteger("0")
127                                 : new BigInteger(indexHeaderValue);
128                 long lastContact = lastContactHeaderValue == null ? 0 : Long
129                                 .parseLong(lastContactHeaderValue);
130                 boolean knownLeader = knownLeaderHeaderValue == null ? false : Boolean
131                                 .parseBoolean(knownLeaderHeaderValue);
132
133                 return new ConsulResponseHeader(lastContact, knownLeader, index);
134         }
135
136         public static <T> ConsulResponse<T> consulResponse(
137                         TypeReference<T> responseType, HttpResponse response) {
138
139                 String indexHeaderValue = response.getFirstHeader("X-Consul-Index")
140                                 .getValue();
141                 String lastContactHeaderValue = response.getFirstHeader(
142                                 "X-Consul-Lastcontact").getValue();
143                 String knownLeaderHeaderValue = response.getFirstHeader(
144                                 "X-Consul-Knownleader").getValue();
145
146                 BigInteger index = indexHeaderValue == null ? new BigInteger("0")
147                                 : new BigInteger(indexHeaderValue);
148                 long lastContact = lastContactHeaderValue == null ? 0 : Long
149                                 .parseLong(lastContactHeaderValue);
150                 boolean knownLeader = knownLeaderHeaderValue == null ? false : Boolean
151                                 .parseBoolean(knownLeaderHeaderValue);
152
153                 ConsulResponse<T> consulResponse = new ConsulResponse<T>(readResponse(
154                                 response, responseType), lastContact, knownLeader, index);
155                 return consulResponse;
156         }
157
158         @SuppressWarnings({ "unchecked", "rawtypes" })
159         public static <T> T readResponse(HttpResponse response,
160                         TypeReference<T> responseType) {
161
162                 // read streamed entity
163                 T object;
164
165                 // HttpEntity,read original data.
166                 Type _type = responseType.getType();
167                 if (_type instanceof Class
168                                 && (((Class) _type).isAssignableFrom(HttpEntity.class))) {
169                         object = (T) response.getEntity();
170                         return object;
171                 }
172
173                 // String,read original data.
174                 if (_type instanceof Class
175                                 && (((Class) _type).isAssignableFrom(String.class))) {
176
177                         try {
178
179                                 object = (T) IOUtils
180                                                 .toString(response.getEntity().getContent());
181                                 response.getEntity().getContent().close();
182
183                         } catch (UnsupportedOperationException e) {
184                                 object = (T) "";
185                                 LOGGER.warn("covert streamed entity to String exception:", e);
186                         } catch (IOException e) {
187                                 object = (T) "";
188                                 LOGGER.warn("covert streamed entity to String exception:", e);
189                         }
190
191                         return object;
192                 }
193
194                 // change data type
195                 try {
196                         object = Jackson.MAPPER.readValue(
197                                         response.getEntity().getContent(), responseType);
198                 } catch (IOException e) {
199                         LOGGER.warn("covert streamed entity to object exception:", e);
200                         object = readDefaultResponse(responseType);
201                 }
202
203                 return object;
204         }
205
206         @SuppressWarnings("unchecked")
207         public static <T> T readDefaultResponse(TypeReference<T> responseType) {
208                 Type _type = responseType.getType();
209                 if (_type instanceof ParameterizedType
210                                 && ((ParameterizedType) _type).getRawType() == List.class) {
211                         return (T) ImmutableList.of();
212                 } else if (_type instanceof ParameterizedType
213                                 && ((ParameterizedType) _type).getRawType() == Map.class) {
214                         return (T) ImmutableMap.of();
215                 } else {
216                         // Not sure if this case will be reached, but if it is it'll be nice
217                         // to know
218                         throw new IllegalStateException(
219                                         "Cannot determine empty representation for " + _type);
220                 }
221         }
222
223         public static boolean isSuccessful(HttpResponse response,
224                         Integer... okCodes) {
225                 return HttpStatus.isSuccess(response.getStatusLine().getStatusCode())
226                                 || Sets.newHashSet(okCodes).contains(
227                                                 response.getStatusLine().getStatusCode());
228         }
229
230         public static String optionsFrom(CatalogOptions catalogOptions,
231                         QueryOptions queryOptions) {
232                 String params = "";
233
234                 if (catalogOptions != null) {
235                         Map<String, Object> options = catalogOptions.toQuery();
236
237                         if (options.containsKey("dc")) {
238                                 params += "dc=" + options.get("dc");
239                         }
240                         if (options.containsKey("tag")) {
241                                 params += params.isEmpty() ? "" : "&";
242                                 params += "tag=" + options.get("tag");
243                         }
244                 }
245
246                 if (queryOptions != null) {
247                         Map<String, Object> options = queryOptions.toQuery();
248
249                         if (options.containsKey("consistent")) {
250                                 params += params.isEmpty() ? "" : "&";
251                                 params += "consistent=" + options.get("consistent");
252                         }
253                         if (options.containsKey("stale")) {
254                                 params += params.isEmpty() ? "" : "&";
255                                 params += "stale=" + options.get("stale");
256                         }
257                         if (options.containsKey("wait")) {
258                                 params += params.isEmpty() ? "" : "&";
259                                 params += "wait=" + options.get("wait");
260                         }
261
262                         if (options.containsKey("index")) {
263                                 params += params.isEmpty() ? "" : "&";
264                                 params += "index=" + options.get("index");
265                         }
266                         if (options.containsKey("token")) {
267                                 params += params.isEmpty() ? "" : "&";
268                                 params += "token=" + options.get("token");
269                         }
270                         if (options.containsKey("near")) {
271                                 params += params.isEmpty() ? "" : "&";
272                                 params += "near=" + options.get("near");
273                         }
274                         if (options.containsKey("dc")) {
275                                 params += params.isEmpty() ? "" : "&";
276                                 params += "dc=" + options.get("dc");
277                         }
278                 }
279                 return params;
280         }
281 }