45e1c753d8e23d28e0828fc0508c234019b353a5
[vfc/nfvo/driver/vnfm/svnfm.git] / huawei / vnfmadapter / VnfmadapterService / service / src / main / java / org / onap / vfc / nfvo / vnfm / svnfm / vnfmadapter / common / restclient / HttpBaseRest.java
1 /*
2  * Copyright 2016 Huawei Technologies Co., Ltd.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 package org.onap.vfc.nfvo.vnfm.svnfm.vnfmadapter.common.restclient;
18
19 import java.io.ByteArrayInputStream;
20 import java.io.IOException;
21 import java.io.UnsupportedEncodingException;
22 import java.net.URLEncoder;
23 import java.text.SimpleDateFormat;
24 import java.util.Calendar;
25 import java.util.Date;
26 import java.util.Map;
27 import java.util.concurrent.atomic.AtomicInteger;
28
29 import org.eclipse.jetty.client.Address;
30 import org.eclipse.jetty.client.HttpClient;
31 import org.eclipse.jetty.client.HttpExchange;
32 import org.eclipse.jetty.http.HttpMethods;
33 import org.slf4j.Logger;
34 import org.slf4j.LoggerFactory;
35
36 /**
37  * <br/>
38  * <p>
39  * </p>
40  * 
41  * @author
42  * @version Aug 9, 2016
43  */
44 public abstract class HttpBaseRest implements Restful {
45
46     private static final Logger LOG = LoggerFactory.getLogger(HttpRest.class);
47
48     final AtomicInteger requestId = new AtomicInteger(0);
49
50     protected HttpClient client = null;
51
52     private static final String LOCAL_HOST = "127.0.0.1";
53
54     static final String HTTP_PATCH = "PATCH";
55
56     String defaultIP = LOCAL_HOST;
57
58     int defaultPort = -10000;
59
60     int defaultTimeout = 30000;
61
62     final String procenameRouteID = "RouteID-" + System.currentTimeMillis() + "-";
63
64     /**
65      * Constructor<br/>
66      * <p>
67      * </p>
68      * 
69      * @since
70      */
71     public HttpBaseRest() {
72         super();
73     }
74
75     protected void createHttpClient() {
76         client = new HttpClient();
77     }
78
79     protected RestHttpContentExchange createRestHttpContentExchange(final RestfulAsyncCallback callback) {
80         final RestHttpContentExchange exchange = new RestHttpContentExchange(true, callback);
81         exchange.setScheme("http");
82         return exchange;
83     }
84
85     private String encodeParams(final RestfulParametes restParametes) throws ServiceException {
86         final Map<String, String> parm = restParametes.getParamMap();
87         String value = null;
88         boolean bHasParma = false;
89         final StringBuilder builder = new StringBuilder();
90         try {
91             for(final String key : parm.keySet()) {
92                 value = parm.get(key);
93                 if(value == null) {
94                     value = "";
95                 }
96                 String str;
97                 if(bHasParma) {
98                     str = String.format("&%s=%s", URLEncoder.encode(key, RestfulClientConst.ENCODING),
99                             URLEncoder.encode(value, RestfulClientConst.ENCODING));
100                 } else {
101                     bHasParma = true;
102                     str = String.format("%s=%s", URLEncoder.encode(key, RestfulClientConst.ENCODING),
103                             URLEncoder.encode(value, RestfulClientConst.ENCODING));
104                 }
105                 builder.append(str);
106             }
107         } catch(final UnsupportedEncodingException ex) {
108             LOG.error("unsupported encoding: ", ex);
109             throw new ServiceException("Broken VM does not support UTF-8");
110         }
111         return builder.toString();
112     }
113
114     private void processHeader(final RestHttpContentExchange contentExchange, final Map<String, String> headerMap) {
115         for(final String key : headerMap.keySet()) {
116             final String value = headerMap.get(key);
117             contentExchange.addRequestHeader(key, value);
118         }
119
120     }
121
122     private void setContentExchangeParams(final RestHttpContentExchange contentExchange) {
123         final String contentType = contentExchange.getRequestFields().getStringField("Content-Type");
124         if(null == contentType || contentType.isEmpty()) {
125             // application/json;charset=utf-8
126             contentExchange.setRequestContentType(RestfulClientConst.APPLICATION_FORM_URLENCODED);
127         }
128         final String encoding = contentExchange.getRequestFields().getStringField("Accept-Encoding");
129         if(null == encoding || encoding.isEmpty()) {
130             // compress,gzip
131             contentExchange.setRequestHeader("Accept-Encoding", "*/*");
132         }
133         contentExchange.setVersion(11);
134     }
135
136     /**
137      * <br/>
138      * 
139      * @param method
140      * @param servicePath
141      * @param restParametes
142      * @param options
143      * @param callback
144      * @return
145      * @throws ServiceException
146      * @since
147      */
148     protected RestfulResponse sendHttpRequest(final String method, final String servicePath,
149             final RestfulParametes restParametes, final RestfulOptions options, final RestfulAsyncCallback callback)
150             throws ServiceException {
151         final RestHttpContentExchange contentExchange = createRestHttpContentExchange(callback);
152         if(null == restParametes) {
153             return new RestfulResponse();
154         }
155         final String requestTrace = this.getReuqestIdString();
156         restParametes.putHttpContextHeader(RestfulClientConst.REQUEST_ID, requestTrace);
157
158         RestfulResponse rsp = null;
159         try {
160             contentExchange.setMethod(method);
161             final String str = encodeParams(restParametes);
162             final StringBuilder builder = new StringBuilder();
163             builder.append(servicePath);
164             if(str.length() > 0 && (method.equals(HttpMethods.GET) || method.equals(HttpMethods.DELETE)
165                     || method.equals(HttpMethods.HEAD))) {
166                 builder.append('?');
167                 builder.append(str);
168             }
169             setDefaultUrl(contentExchange, options, builder);
170             processHeader(contentExchange, restParametes.getHeaderMap());
171             setContentExchangeParams(contentExchange);
172
173             setPostPutParam(method, restParametes, contentExchange, str);
174             setTimeout(options, contentExchange);
175
176             client.send(contentExchange);
177             rsp = callbackExecute(callback, contentExchange);
178         } catch(final Exception e) {
179             LOG.error("request reply message have exception:status is "
180                     + RestHttpContentExchange.toState(contentExchange.getStatus()));
181             throw new ServiceException(e);
182         }
183         return rsp;
184     }
185
186     private void setDefaultUrl(final RestHttpContentExchange contentExchange, final RestfulOptions options,
187             final StringBuilder url) {
188         // server
189         if(url.toString().startsWith("http")) {
190             contentExchange.setURL(url.toString());
191         } else {
192             String host = defaultIP;
193             int iPort = defaultPort;
194             if(options != null) {
195                 host = options.getHost();
196                 if(host.isEmpty()) {
197                     host = defaultIP;
198                 }
199                 iPort = options.getPort();
200                 if(iPort == 0) {
201                     iPort = defaultPort;
202                 }
203             }
204             // Integer.getInteger(".http.client.maxThread",30)
205             contentExchange.setAddress(new Address(host, iPort));
206             contentExchange.setRequestURI(url.toString());
207         }
208     }
209
210     private String getReuqestIdString() {
211         if(this.requestId.get() == 0x7FFFFFFF) {
212             this.requestId.set(1);
213         }
214         final int reqId = this.requestId.getAndIncrement();
215         final StringBuilder builder = new StringBuilder(this.procenameRouteID);
216         // time
217         final SimpleDateFormat dateFormate = new SimpleDateFormat("yyMMdd");
218         final SimpleDateFormat timeFormate = new SimpleDateFormat("HHmmss");
219         final Date date = Calendar.getInstance().getTime();
220         builder.append(dateFormate.format(date) + timeFormate.format(date));
221         builder.append('-');
222         builder.append(reqId);
223         return builder.toString();
224     }
225
226     private void setPostPutParam(final String method, final RestfulParametes restParametes,
227             final RestHttpContentExchange contentExchange, final String str) throws UnsupportedEncodingException {
228         if(HttpMethods.POST.equals(method) || HttpMethods.PUT.equals(method) || HTTP_PATCH.equals(method)) {
229             ByteArrayInputStream buff;
230             final String tmpRaw = restParametes.getRawData();
231             if(tmpRaw == null) {
232                 buff = new ByteArrayInputStream(str.getBytes(RestfulClientConst.ENCODING));
233             } else {
234                 buff = new ByteArrayInputStream(tmpRaw.getBytes(RestfulClientConst.ENCODING));
235             }
236             final int len = buff.available();
237             contentExchange.setRequestContentSource(buff);
238             contentExchange.setRequestHeader("content-length", String.valueOf(len));
239         }
240     }
241
242     private void setTimeout(final RestfulOptions options, final RestHttpContentExchange contentExchange) {
243         if(options != null) {
244             final long timeout = options.getRestTimeout();
245             if(timeout != 0) {
246                 contentExchange.setTimeout(timeout);
247             } else {
248                 contentExchange.setTimeout(defaultTimeout);
249             }
250         } else {
251             contentExchange.setTimeout(defaultTimeout);
252         }
253     }
254
255     private RestfulResponse callbackExecute(final RestfulAsyncCallback callback,
256             final RestHttpContentExchange contentExchange) throws InterruptedException, IOException, ServiceException {
257         if(callback == null) {
258             final int exchangeState = contentExchange.waitForDone();
259             if(exchangeState == HttpExchange.STATUS_COMPLETED) {
260                 return contentExchange.getResponse();
261             } else if(exchangeState == HttpExchange.STATUS_EXCEPTED) {
262                 throw new ServiceException(
263                         "request is exception: " + RestHttpContentExchange.toState(HttpExchange.STATUS_EXCEPTED));
264             } else if(exchangeState == HttpExchange.STATUS_EXPIRED) {
265                 throw new ServiceException(
266                         "request is expierd: " + RestHttpContentExchange.toState(HttpExchange.STATUS_EXPIRED));
267             }
268         }
269         return null;
270     }
271
272 }