71937245bc244a32ccf24c754a1264f05c4431a9
[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 import org.onap.so.logger.MsoAlarmLogger;
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         private static MsoAlarmLogger alarmLogger = new MsoAlarmLogger();
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                 String action = bpelRequest.getRequestHeader().getSvcAction();
88                 String operation = bpelRequest.getRequestHeader().getSvcOperation();
89                 String bpelReqId = bpelRequest.getRequestHeader().getRequestId();
90                 String callbackUrl = bpelRequest.getRequestHeader().getCallbackUrl();
91
92                 String sdncReqBody = null;
93
94         
95
96                 RequestTunables rt = new RequestTunables(bpelReqId,
97                                 bpelRequest.getRequestHeader().getMsoAction(),
98                                 bpelRequest.getRequestHeader().getSvcOperation(),
99                                 bpelRequest.getRequestHeader().getSvcAction());         
100                 rt = tunablesMapper.setTunables(rt);
101                 rt.setSdncaNotificationUrl(env.getProperty(Constants.MY_URL_PROP));
102
103
104                 if ("POST".equals(rt.getReqMethod()))
105                 {
106                         Node node = (Node)      bpelRequest.getRequestData();
107                 Document reqDoc = node.getOwnerDocument();
108                         sdncReqBody = Utils.genSdncReq(reqDoc, rt);
109                 }
110                 else if("PUT".equals(rt.getReqMethod())){
111                         Node node = (Node)      bpelRequest.getRequestData();
112                 Document reqDoc = node.getOwnerDocument();
113                         sdncReqBody = Utils.genSdncPutReq(reqDoc, rt);
114                 }
115                 long sdncStartTime = System.currentTimeMillis();
116                 SDNCResponse sdncResp = getSdncResp(sdncReqBody, rt);
117                 msoLogger.recordMetricEvent (sdncStartTime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully received response from SDNC", "SDNC", action + "." + operation, null);
118                 msoLogger.debug ("Got the SDNC Response: " + sdncResp.getSdncRespXml());
119                 long bpelStartTime = System.currentTimeMillis();
120                 sendRespToBpel(callbackUrl, sdncResp);
121                 msoLogger.recordMetricEvent (bpelStartTime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully send reauest to BPEL", "BPMN", callbackUrl, null);
122                 return;
123         }
124
125         public SDNCResponse getSdncResp(String sdncReqBody, RequestTunables rt)
126         {
127
128                 URL url;
129                 HttpURLConnection con = null;
130                 DataOutputStream out = null;
131                 BufferedReader in = null;
132                 SDNCResponse sdncResp = new SDNCResponse(rt.getReqId());
133                 StringBuilder response = new StringBuilder();
134
135                 msoLogger.info(MessageEnum.RA_SEND_REQUEST_SDNC.name() + ":\n" + rt.toString(), "SDNC", "");
136                 msoLogger.trace("SDNC Request Body:\n" + sdncReqBody);
137
138                 try {
139
140                         url = new URL(rt.getSdncUrl());
141
142                         con = (HttpURLConnection) url.openConnection();
143                     con.setConnectTimeout(Integer.parseInt(env.getProperty(Constants.SDNC_CONNECTTIME_PROP)));
144                     con.setReadTimeout(Integer.parseInt(rt.getTimeout()));
145                         con.setRequestProperty("Accept", "application/yang.data+xml"); //for response in xml
146                         String userCredentials = CryptoUtils.decryptProperty(env.getProperty(Constants.SDNC_AUTH_PROP), Constants.DEFAULT_SDNC_AUTH, Constants.ENCRYPTION_KEY);
147
148                         String basicAuth = "Basic " + DatatypeConverter.printBase64Binary(userCredentials.getBytes());
149                         con.setRequestProperty ("Authorization", basicAuth);
150                     con.setRequestMethod(rt.getReqMethod());
151
152                         // Add request headers
153                     if ("POST".equals(rt.getReqMethod()) || "PUT".equals(rt.getReqMethod()))
154                     {
155                         con.setRequestProperty("Content-type", "application/xml");
156                         con.setRequestProperty("Content-length",String.valueOf(sdncReqBody.length()));
157                                 con.setDoOutput(true);
158                                 out = new DataOutputStream(con.getOutputStream());
159                                 out.writeBytes(sdncReqBody);
160                                 out.flush();
161                                 out.close();
162                     }
163
164                         //Get response
165                         sdncResp.setRespCode(con.getResponseCode());
166                         sdncResp.setRespMsg(con.getResponseMessage());
167
168                         if (con.getResponseCode()>= 200 && con.getResponseCode()<=299) { 
169                                 in = new BufferedReader(new InputStreamReader(con.getInputStream()));   
170                                 String inputLine;
171                                 //Not parsing the response -it contains a responseHdr section and data section
172                                 while ((inputLine = in.readLine()) != null) {
173                                         response.append(inputLine);
174                                 }
175                                 in.close();
176                         }
177                         
178                         sdncResp.setSdncRespXml(response.toString());
179                         msoLogger.info(MessageEnum.RA_RESPONSE_FROM_SDNC.name() + ":\n" + sdncResp.toString(), "SDNC", "");
180                         return(sdncResp);
181                 }
182                 catch (Exception e)
183                 {
184                         msoLogger.error(MessageEnum.RA_EXCEPTION_COMMUNICATE_SDNC, "SDNC", "", MsoLogger.ErrorCode.BusinessProcesssError, "Exception processing request to SDNC", e);
185                         //default
186                         sdncResp.setRespCode(HttpURLConnection.HTTP_INTERNAL_ERROR);
187                         String respMsg = "Error processing request to SDNC. ";
188                         StringBuilder sdncErrMsg = new StringBuilder();
189
190                         if (e instanceof java.net.SocketTimeoutException )
191                         {
192                                 sdncResp.setRespCode(HttpURLConnection.HTTP_CLIENT_TIMEOUT);
193                                 respMsg = "Request to SDNC timed out. ";
194                         }
195                         if (con != null)
196                         {
197                                 try { //e1
198                                         if (con.getResponseCode() != HttpURLConnection.HTTP_OK) //seen in SocketException connection reset 
199                                                 sdncResp.setRespCode(con.getResponseCode());
200                                         respMsg = respMsg + con.getResponseMessage() + ". ";
201                                         InputStream is = con.getErrorStream();
202                                         if (is != null)
203                                         {
204                                                 XPathFactory xpathFactory = XPathFactory.newInstance();
205                                             XPath xpath = xpathFactory.newXPath();
206                                                 DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
207                         dbf.setFeature (XMLConstants.FEATURE_SECURE_PROCESSING, true);
208                                                 dbf.setFeature("http://xml.org/sax/features/external-general-entities", false);
209                                                 dbf.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
210                                                 DocumentBuilder db;
211                                                 Document doc = null;
212                                                 try { //e2
213                                                         db = dbf.newDocumentBuilder();
214                                                         doc = db.parse(is);
215                                                         NodeList errors = (NodeList)xpath.evaluate("errors/error", doc, XPathConstants.NODESET);
216                                                         for (int i = 0; i < errors.getLength(); i++)
217                                                         {
218                                                                 Element error = (Element) errors.item(i);
219                                                                 String eType = null;
220                                                                 try {
221                                                                         eType = xpath.evaluate("error-type", error);
222                                                                         sdncErrMsg = new StringBuilder(". SDNC Returned-[error-type:" + eType);
223                                                                 } catch (Exception e3) {
224                                                                     msoLogger.error (MessageEnum.RA_EVALUATE_XPATH_ERROR, "error-type", error.toString(), "SDNC", "", MsoLogger.ErrorCode.DataError, EXCEPTION_MSG, e3);
225                                                                 }
226
227                                                                 String eTag = null;
228                                                                 try {
229                                                                         eTag = xpath.evaluate( "error-tag", error);
230                                                                         sdncErrMsg.append(", error-tag:").append(eTag);
231                                                                 } catch (Exception e3) {
232                                                                         msoLogger.error (MessageEnum.RA_EVALUATE_XPATH_ERROR, "error-tag", error.toString(), "SDNC", "", MsoLogger.ErrorCode.DataError, EXCEPTION_MSG, e3);
233                                                                 }
234
235                                                                 String eMsg = null;
236                                                                 try {
237                                                                         eMsg = xpath.evaluate("error-message", error);
238                                                                         sdncErrMsg.append(", error-message:").append(eMsg).append("]");
239                                                                 } catch (Exception e3) {
240                                                                         msoLogger.error (MessageEnum.RA_EVALUATE_XPATH_ERROR, "error-message", error.toString(), "SDNC", "", MsoLogger.ErrorCode.DataError, EXCEPTION_MSG, e3);
241                                                                 }
242                                                         }
243                                                 } catch (Exception e2) {
244                                                     msoLogger.error (MessageEnum.RA_ANALYZE_ERROR_EXC, "SDNC", "", MsoLogger.ErrorCode.DataError, "Exception while analyse error", e2);
245                                                 }
246                                         } //is != null
247                                 } catch (Exception e1) {
248                                         msoLogger.error (MessageEnum.RA_ERROR_GET_RESPONSE_SDNC, "SDNC", "", MsoLogger.ErrorCode.BusinessProcesssError, "Exception while get SDNC response", e1);
249                                 }
250                         } //con != null
251
252                         if (e.getMessage() != null) {
253                 respMsg = respMsg + e.getMessage();
254             }
255             respMsg = respMsg + sdncErrMsg;
256
257                         sdncResp.setRespMsg(respMsg);
258
259                         msoLogger.error(MessageEnum.RA_EXCEPTION_COMMUNICATE_SDNC, "SDNC", "", MsoLogger.ErrorCode.AvailabilityError, "Exception while communicate with SDNC", e);
260                         alarmLogger.sendAlarm(MSO_INTERNAL_ERROR, MsoAlarmLogger.CRITICAL, respMsg);
261                         return sdncResp;
262                 }
263                 finally
264                 {
265                         if (con != null) {
266                 con.disconnect();
267             }
268                 }
269         }
270
271         public void sendRespToBpel(String bpelUrl, SDNCResponse sdncResp)
272         {
273                 String error;
274                 try
275                 {
276                         SDNCAdapterCallbackRequest cbReq = new SDNCAdapterCallbackRequest();
277                         cbReq.setCallbackHeader(new CallbackHeader(sdncResp.getReqId(), Integer.toString(sdncResp.getRespCode()), sdncResp.getRespMsg()));
278                         if (sdncResp.getSdncRespXml() != null)
279                         {
280                                 cbReq.setRequestData(sdncResp.getSdncRespXml());
281                         }
282                         msoLogger.info(MessageEnum.RA_CALLBACK_BPEL.name() + ":\n" + cbReq.toString(), CAMUNDA, "");
283
284                         URL wsdlUrl = null;
285                         try {
286                                 wsdlUrl = new URL (bpelUrl);
287                         } catch (MalformedURLException e1) {
288                                 error = "Caught exception initializing Callback wsdl " + e1.getMessage();
289                                 msoLogger.error(MessageEnum.RA_INIT_CALLBACK_WSDL_ERR, CAMUNDA, "", MsoLogger.ErrorCode.DataError, "Exception initializing Callback wsdl", e1);
290                                 alarmLogger.sendAlarm(MSO_INTERNAL_ERROR, MsoAlarmLogger.CRITICAL, error);
291                         }
292
293                         SDNCCallbackAdapterService cbSvc = new SDNCCallbackAdapterService();
294
295                         SDNCCallbackAdapterPortType cbPort = cbSvc.getSDNCCallbackAdapterSoapHttpPort();
296
297                         BindingProvider bp = (BindingProvider)cbPort;
298                         
299                         if(null != wsdlUrl) {
300                         bp.getRequestContext().put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY, wsdlUrl.toExternalForm());
301                         }
302                         else {
303                             msoLogger.debug("wsdlUrl is NULL:");
304                         }
305
306                         //authentication
307                         try
308                         {
309                                 Map<String, Object> reqCtx = bp.getRequestContext();
310                                 Map<String, List<String>> headers = new HashMap<>();
311                                 String userCredentials = CryptoUtils.decryptProperty(env.getProperty(Constants.BPEL_AUTH_PROP), Constants.DEFAULT_BPEL_AUTH, Constants.ENCRYPTION_KEY);
312
313                                 String basicAuth = "Basic " + DatatypeConverter.printBase64Binary(userCredentials.getBytes());
314                                 reqCtx.put(MessageContext.HTTP_REQUEST_HEADERS, headers);
315                                 headers.put ("Authorization", Collections.singletonList(basicAuth));
316                         }
317                         catch (Exception e2) {
318                                 error = "Unable to set authorization in callback request " + e2.getMessage();
319                                 msoLogger.error(MessageEnum.RA_SET_CALLBACK_AUTH_EXC, CAMUNDA, "", MsoLogger.ErrorCode.BusinessProcesssError, "Exception - Unable to set authorization in callback request", e2);
320                                 alarmLogger.sendAlarm(MSO_INTERNAL_ERROR, MsoAlarmLogger.CRITICAL, error);
321                         }
322
323                         msoLogger.debug("Invoking Bpel Callback. BpelCallbackUrl:" + bpelUrl);
324                         cbPort.sdncAdapterCallback(cbReq);
325
326                 }
327                 catch (Exception e)
328                 {
329                         error = "Error sending BpelCallback request" + e.getMessage();
330                         msoLogger.error("Error " + MsoLogger.ErrorCode.BusinessProcesssError + " - " + MessageEnum.RA_CALLBACK_BPEL_EXC + " - " + error, e);
331                         alarmLogger.sendAlarm(MSO_INTERNAL_ERROR, MsoAlarmLogger.CRITICAL, error);
332                 }
333                 msoLogger.info(MessageEnum.RA_CALLBACK_BPEL_COMPLETE.name(), CAMUNDA, "");
334                 return;
335         }
336
337 }