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