Merge 'origin/casablanca' into master
[so.git] / adapters / mso-sdnc-adapter / src / main / java / org / onap / so / adapters / sdnc / impl / SDNCRestClient.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * ONAP - SO
4  * ================================================================================
5  * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
6  * Copyright (C) 2017 Huawei Technologies Co., Ltd. All rights reserved.
7  * ================================================================================
8  * Modifications Copyright (C) 2018 IBM.
9  * ================================================================================
10  * Licensed under the Apache License, Version 2.0 (the "License");
11  * you may not use this file except in compliance with the License.
12  * You may obtain a copy of the License at
13  * 
14  *      http://www.apache.org/licenses/LICENSE-2.0
15  * 
16  * Unless required by applicable law or agreed to in writing, software
17  * distributed under the License is distributed on an "AS IS" BASIS,
18  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19  * See the License for the specific language governing permissions and
20  * limitations under the License.
21  * ============LICENSE_END=========================================================
22  */
23
24 package org.onap.so.adapters.sdnc.impl;
25
26
27 import java.io.BufferedReader;
28 import java.io.DataOutputStream;
29 import java.io.InputStream;
30 import java.io.InputStreamReader;
31 import java.net.HttpURLConnection;
32 import java.net.MalformedURLException;
33 import java.net.URL;
34 import java.util.Collections;
35 import java.util.HashMap;
36 import java.util.List;
37 import java.util.Map;
38
39 import javax.xml.XMLConstants;
40 import javax.xml.bind.DatatypeConverter;
41 import javax.xml.parsers.DocumentBuilder;
42 import javax.xml.parsers.DocumentBuilderFactory;
43 import javax.xml.ws.BindingProvider;
44 import javax.xml.ws.handler.MessageContext;
45 import javax.xml.xpath.XPath;
46 import javax.xml.xpath.XPathConstants;
47 import javax.xml.xpath.XPathFactory;
48 import org.onap.so.utils.CryptoUtils;
49 import org.onap.so.adapters.sdnc.SDNCAdapterRequest;
50 import org.onap.so.adapters.sdnc.client.CallbackHeader;
51 import org.onap.so.adapters.sdnc.client.SDNCAdapterCallbackRequest;
52 import org.onap.so.adapters.sdnc.client.SDNCCallbackAdapterPortType;
53 import org.onap.so.adapters.sdnc.client.SDNCCallbackAdapterService;
54 import org.onap.so.logger.MessageEnum;
55
56 import org.onap.so.logger.MsoLogger;
57 import org.springframework.beans.factory.annotation.Autowired;
58 import org.springframework.core.env.Environment;
59 import org.springframework.scheduling.annotation.Async;
60 import org.springframework.stereotype.Component;
61 import org.w3c.dom.Document;
62 import org.w3c.dom.Element;
63 import org.w3c.dom.Node;
64 import org.w3c.dom.NodeList;
65
66
67 @Component
68 public class SDNCRestClient{
69
70         @Autowired
71         private Environment env;
72         
73         @Autowired
74         private MapRequestTunables tunablesMapper;
75
76         private static MsoLogger msoLogger = MsoLogger.getMsoLogger(MsoLogger.Catalog.RA,SDNCRestClient.class);
77
78     private static final String EXCEPTION_MSG="Exception while evaluate xpath";
79     private static final String MSO_INTERNAL_ERROR="MsoInternalError";
80     private static final String CAMUNDA="Camunda";
81         @Async
82         public void executeRequest(SDNCAdapterRequest bpelRequest)
83         {
84                 
85                 msoLogger.debug("BPEL Request:" + bpelRequest.toString());
86
87                 // Added delay to allow completion of create request to SDNC
88                 // before executing activate of create request.
89                 try {
90                         Thread.sleep(5000);
91                 } catch (InterruptedException e) {
92                         e.printStackTrace();
93                 }
94
95                 String action = bpelRequest.getRequestHeader().getSvcAction();
96                 String operation = bpelRequest.getRequestHeader().getSvcOperation();
97                 String bpelReqId = bpelRequest.getRequestHeader().getRequestId();
98                 String callbackUrl = bpelRequest.getRequestHeader().getCallbackUrl();
99
100                 String sdncReqBody = null;
101
102         
103
104                 RequestTunables rt = new RequestTunables(bpelReqId,
105                                 bpelRequest.getRequestHeader().getMsoAction(),
106                                 bpelRequest.getRequestHeader().getSvcOperation(),
107                                 bpelRequest.getRequestHeader().getSvcAction());         
108                 rt = tunablesMapper.setTunables(rt);
109                 rt.setSdncaNotificationUrl(env.getProperty(Constants.MY_URL_PROP));
110
111
112                 if ("POST".equals(rt.getReqMethod()))
113                 {
114                         Node node = (Node)      bpelRequest.getRequestData();
115                 Document reqDoc = node.getOwnerDocument();
116                         sdncReqBody = Utils.genSdncReq(reqDoc, rt);
117                 }
118                 else if("PUT".equals(rt.getReqMethod())){
119                         Node node = (Node)      bpelRequest.getRequestData();
120                 Document reqDoc = node.getOwnerDocument();
121                         sdncReqBody = Utils.genSdncPutReq(reqDoc, rt);
122                 }
123                 long sdncStartTime = System.currentTimeMillis();
124                 SDNCResponse sdncResp = getSdncResp(sdncReqBody, rt);
125                 msoLogger.recordMetricEvent (sdncStartTime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully received response from SDNC", "SDNC", action + "." + operation, null);
126                 msoLogger.debug ("Got the SDNC Response: " + sdncResp.getSdncRespXml());
127                 long bpelStartTime = System.currentTimeMillis();
128                 sendRespToBpel(callbackUrl, sdncResp);
129                 msoLogger.recordMetricEvent (bpelStartTime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully send reauest to BPEL", "BPMN", callbackUrl, null);
130                 return;
131         }
132
133         public SDNCResponse getSdncResp(String sdncReqBody, RequestTunables rt)
134         {
135
136                 URL url;
137                 HttpURLConnection con = null;
138                 DataOutputStream out = null;
139                 BufferedReader in = null;
140                 SDNCResponse sdncResp = new SDNCResponse(rt.getReqId());
141                 StringBuilder response = new StringBuilder();
142
143                 msoLogger.info(MessageEnum.RA_SEND_REQUEST_SDNC.name() + ":\n" + rt.toString(), "SDNC", "");
144                 msoLogger.trace("SDNC Request Body:\n" + sdncReqBody);
145
146                 try {
147
148                         url = new URL(rt.getSdncUrl());
149
150                         con = (HttpURLConnection) url.openConnection();
151                     con.setConnectTimeout(Integer.parseInt(env.getProperty(Constants.SDNC_CONNECTTIME_PROP)));
152                     con.setReadTimeout(Integer.parseInt(rt.getTimeout()));
153                         con.setRequestProperty("Accept", "application/yang.data+xml"); //for response in xml
154                         String userCredentials = CryptoUtils.decrypt(env.getProperty(Constants.SDNC_AUTH_PROP), env.getProperty(Constants.ENCRYPTION_KEY_PROP));
155
156                         String basicAuth = "Basic " + DatatypeConverter.printBase64Binary(userCredentials.getBytes());
157                         con.setRequestProperty ("Authorization", basicAuth);
158                     con.setRequestMethod(rt.getReqMethod());
159
160                         // Add request headers
161                     if ("POST".equals(rt.getReqMethod()) || "PUT".equals(rt.getReqMethod()))
162                     {
163                         con.setRequestProperty("Content-type", "application/xml");
164                         con.setRequestProperty("Content-length",String.valueOf(sdncReqBody.length()));
165                                 con.setDoOutput(true);
166                                 out = new DataOutputStream(con.getOutputStream());
167                                 out.writeBytes(sdncReqBody);
168                                 out.flush();
169                                 out.close();
170                     }
171
172                         //Get response
173                         sdncResp.setRespCode(con.getResponseCode());
174                         sdncResp.setRespMsg(con.getResponseMessage());
175
176                         if (con.getResponseCode()>= 200 && con.getResponseCode()<=299) { 
177                                 in = new BufferedReader(new InputStreamReader(con.getInputStream()));   
178                                 String inputLine;
179                                 //Not parsing the response -it contains a responseHdr section and data section
180                                 while ((inputLine = in.readLine()) != null) {
181                                         response.append(inputLine);
182                                 }
183                                 in.close();
184                         }
185                         
186                         sdncResp.setSdncRespXml(response.toString());
187                         msoLogger.info(MessageEnum.RA_RESPONSE_FROM_SDNC.name() + ":\n" + sdncResp.toString(), "SDNC", "");
188                         return(sdncResp);
189                 }
190                 catch (Exception e)
191                 {
192                         msoLogger.error(MessageEnum.RA_EXCEPTION_COMMUNICATE_SDNC, "SDNC", "", MsoLogger.ErrorCode.BusinessProcesssError, "Exception processing request to SDNC", e);
193                         //default
194                         sdncResp.setRespCode(HttpURLConnection.HTTP_INTERNAL_ERROR);
195                         String respMsg = "Error processing request to SDNC. ";
196                         StringBuilder sdncErrMsg = new StringBuilder();
197
198                         if (e instanceof java.net.SocketTimeoutException )
199                         {
200                                 sdncResp.setRespCode(HttpURLConnection.HTTP_CLIENT_TIMEOUT);
201                                 respMsg = "Request to SDNC timed out. ";
202                         }
203                         if (con != null)
204                         {
205                                 try { //e1
206                                         if (con.getResponseCode() != HttpURLConnection.HTTP_OK) //seen in SocketException connection reset 
207                                                 sdncResp.setRespCode(con.getResponseCode());
208                                         respMsg = respMsg + con.getResponseMessage() + ". ";
209                                         InputStream is = con.getErrorStream();
210                                         if (is != null)
211                                         {
212                                                 XPathFactory xpathFactory = XPathFactory.newInstance();
213                                             XPath xpath = xpathFactory.newXPath();
214                                                 DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
215                         dbf.setFeature (XMLConstants.FEATURE_SECURE_PROCESSING, true);
216                                                 dbf.setFeature("http://xml.org/sax/features/external-general-entities", false);
217                                                 dbf.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
218                                                 DocumentBuilder db;
219                                                 Document doc = null;
220                                                 try { //e2
221                                                         db = dbf.newDocumentBuilder();
222                                                         doc = db.parse(is);
223                                                         NodeList errors = (NodeList)xpath.evaluate("errors/error", doc, XPathConstants.NODESET);
224                                                         for (int i = 0; i < errors.getLength(); i++)
225                                                         {
226                                                                 Element error = (Element) errors.item(i);
227                                                                 String eType = null;
228                                                                 try {
229                                                                         eType = xpath.evaluate("error-type", error);
230                                                                         sdncErrMsg = new StringBuilder(". SDNC Returned-[error-type:" + eType);
231                                                                 } catch (Exception e3) {
232                                                                     msoLogger.error (MessageEnum.RA_EVALUATE_XPATH_ERROR, "error-type", error.toString(), "SDNC", "", MsoLogger.ErrorCode.DataError, EXCEPTION_MSG, e3);
233                                                                 }
234
235                                                                 String eTag = null;
236                                                                 try {
237                                                                         eTag = xpath.evaluate( "error-tag", error);
238                                                                         sdncErrMsg.append(", error-tag:").append(eTag);
239                                                                 } catch (Exception e3) {
240                                                                         msoLogger.error (MessageEnum.RA_EVALUATE_XPATH_ERROR, "error-tag", error.toString(), "SDNC", "", MsoLogger.ErrorCode.DataError, EXCEPTION_MSG, e3);
241                                                                 }
242
243                                                                 String eMsg = null;
244                                                                 try {
245                                                                         eMsg = xpath.evaluate("error-message", error);
246                                                                         sdncErrMsg.append(", error-message:").append(eMsg).append("]");
247                                                                 } catch (Exception e3) {
248                                                                         msoLogger.error (MessageEnum.RA_EVALUATE_XPATH_ERROR, "error-message", error.toString(), "SDNC", "", MsoLogger.ErrorCode.DataError, EXCEPTION_MSG, e3);
249                                                                 }
250                                                         }
251                                                 } catch (Exception e2) {
252                                                     msoLogger.error (MessageEnum.RA_ANALYZE_ERROR_EXC, "SDNC", "", MsoLogger.ErrorCode.DataError, "Exception while analyse error", e2);
253                                                 }
254                                         } //is != null
255                                 } catch (Exception e1) {
256                                         msoLogger.error (MessageEnum.RA_ERROR_GET_RESPONSE_SDNC, "SDNC", "", MsoLogger.ErrorCode.BusinessProcesssError, "Exception while get SDNC response", e1);
257                                 }
258                         } //con != null
259
260                         if (e.getMessage() != null) {
261                 respMsg = respMsg + e.getMessage();
262             }
263             respMsg = respMsg + sdncErrMsg;
264
265                         sdncResp.setRespMsg(respMsg);
266
267                         msoLogger.error(MessageEnum.RA_EXCEPTION_COMMUNICATE_SDNC, "SDNC", "", MsoLogger.ErrorCode.AvailabilityError, "Exception while communicate with SDNC", e);
268
269                         return sdncResp;
270                 }
271                 finally
272                 {
273                         if (con != null) {
274                 con.disconnect();
275             }
276                 }
277         }
278
279         public void sendRespToBpel(String bpelUrl, SDNCResponse sdncResp)
280         {
281                 String error;
282                 try
283                 {
284                         SDNCAdapterCallbackRequest cbReq = new SDNCAdapterCallbackRequest();
285                         cbReq.setCallbackHeader(new CallbackHeader(sdncResp.getReqId(), Integer.toString(sdncResp.getRespCode()), sdncResp.getRespMsg()));
286                         if (sdncResp.getSdncRespXml() != null)
287                         {
288                                 cbReq.setRequestData(sdncResp.getSdncRespXml());
289                         }
290                         msoLogger.info(MessageEnum.RA_CALLBACK_BPEL.name() + ":\n" + cbReq.toString(), CAMUNDA, "");
291
292                         URL wsdlUrl = null;
293                         try {
294                                 wsdlUrl = new URL (bpelUrl);
295                         } catch (MalformedURLException e1) {
296                                 error = "Caught exception initializing Callback wsdl " + e1.getMessage();
297                                 msoLogger.error(MessageEnum.RA_INIT_CALLBACK_WSDL_ERR, CAMUNDA, "", MsoLogger.ErrorCode.DataError, "Exception initializing Callback wsdl", e1);
298
299                         }
300
301                         SDNCCallbackAdapterService cbSvc = new SDNCCallbackAdapterService();
302
303                         SDNCCallbackAdapterPortType cbPort = cbSvc.getSDNCCallbackAdapterSoapHttpPort();
304
305                         BindingProvider bp = (BindingProvider)cbPort;
306                         
307                         if(null != wsdlUrl) {
308                         bp.getRequestContext().put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY, wsdlUrl.toExternalForm());
309                         }
310                         else {
311                             msoLogger.debug("wsdlUrl is NULL:");
312                         }
313
314                         //authentication
315                         try
316                         {
317                                 Map<String, Object> reqCtx = bp.getRequestContext();
318                                 Map<String, List<String>> headers = new HashMap<>();
319                                 String userCredentials = CryptoUtils.decrypt(env.getProperty(Constants.BPEL_AUTH_PROP), env.getProperty(Constants.ENCRYPTION_KEY_PROP));
320
321                                 String basicAuth = "Basic " + DatatypeConverter.printBase64Binary(userCredentials.getBytes());
322                                 reqCtx.put(MessageContext.HTTP_REQUEST_HEADERS, headers);
323                                 headers.put ("Authorization", Collections.singletonList(basicAuth));
324                         }
325                         catch (Exception e2) {
326                                 error = "Unable to set authorization in callback request " + e2.getMessage();
327                                 msoLogger.error(MessageEnum.RA_SET_CALLBACK_AUTH_EXC, CAMUNDA, "", MsoLogger.ErrorCode.BusinessProcesssError, "Exception - Unable to set authorization in callback request", e2);
328
329                         }
330
331                         msoLogger.debug("Invoking Bpel Callback. BpelCallbackUrl:" + bpelUrl);
332                         cbPort.sdncAdapterCallback(cbReq);
333
334                 }
335                 catch (Exception e)
336                 {
337                         error = "Error sending BpelCallback request" + e.getMessage();
338                         msoLogger.error("Error " + MsoLogger.ErrorCode.BusinessProcesssError + " - " + MessageEnum.RA_CALLBACK_BPEL_EXC + " - " + error, e);
339
340                 }
341                 msoLogger.info(MessageEnum.RA_CALLBACK_BPEL_COMPLETE.name(), CAMUNDA, "");
342                 return;
343         }
344
345 }