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