2 * ============LICENSE_START=======================================================
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 * 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
15 * http://www.apache.org/licenses/LICENSE-2.0
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=========================================================
25 package org.onap.so.adapters.sdnc.impl;
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;
35 import java.util.Collections;
36 import java.util.HashMap;
37 import java.util.List;
40 import javax.xml.XMLConstants;
41 import javax.xml.bind.DatatypeConverter;
42 import javax.xml.parsers.DocumentBuilder;
43 import javax.xml.parsers.DocumentBuilderFactory;
44 import javax.xml.ws.BindingProvider;
45 import javax.xml.ws.handler.MessageContext;
46 import javax.xml.xpath.XPath;
47 import javax.xml.xpath.XPathConstants;
48 import javax.xml.xpath.XPathFactory;
50 import org.onap.so.logger.ErrorCode;
51 import org.onap.so.utils.CryptoUtils;
52 import org.onap.so.adapters.sdnc.SDNCAdapterRequest;
53 import org.onap.so.adapters.sdnc.client.CallbackHeader;
54 import org.onap.so.adapters.sdnc.client.SDNCAdapterCallbackRequest;
55 import org.onap.so.adapters.sdnc.client.SDNCCallbackAdapterPortType;
56 import org.onap.so.adapters.sdnc.client.SDNCCallbackAdapterService;
57 import org.onap.so.logger.MessageEnum;
59 import org.slf4j.Logger;
60 import org.slf4j.LoggerFactory;
61 import org.springframework.beans.factory.annotation.Autowired;
62 import org.springframework.core.env.Environment;
63 import org.springframework.scheduling.annotation.Async;
64 import org.springframework.stereotype.Component;
65 import org.w3c.dom.Document;
66 import org.w3c.dom.Element;
67 import org.w3c.dom.Node;
68 import org.w3c.dom.NodeList;
72 public class SDNCRestClient{
75 private Environment env;
78 private MapRequestTunables tunablesMapper;
80 private static Logger logger = LoggerFactory.getLogger(SDNCRestClient.class);
82 private static final String EXCEPTION_MSG="Exception while evaluate xpath";
83 private static final String MSO_INTERNAL_ERROR="MsoInternalError";
84 private static final String CAMUNDA="Camunda";
86 public void executeRequest(SDNCAdapterRequest bpelRequest)
89 logger.debug("BPEL Request:" + bpelRequest.toString());
91 // Added delay to allow completion of create request to SDNC
92 // before executing activate of create request.
95 } catch (InterruptedException e) {
96 logger.error("{} {} {} {}", MessageEnum.BPMN_GENERAL_EXCEPTION.toString(), "SDNC",
97 ErrorCode.UnknownError.getValue(), "Exception processing request to SDNC", e);
99 Thread.currentThread().interrupt();
102 String action = bpelRequest.getRequestHeader().getSvcAction();
103 String operation = bpelRequest.getRequestHeader().getSvcOperation();
104 String bpelReqId = bpelRequest.getRequestHeader().getRequestId();
105 String callbackUrl = bpelRequest.getRequestHeader().getCallbackUrl();
107 String sdncReqBody = null;
109 RequestTunables rt = new RequestTunables(bpelReqId,
110 bpelRequest.getRequestHeader().getMsoAction(),
111 bpelRequest.getRequestHeader().getSvcOperation(),
112 bpelRequest.getRequestHeader().getSvcAction());
113 rt = tunablesMapper.setTunables(rt);
114 rt.setSdncaNotificationUrl(env.getProperty(Constants.MY_URL_PROP));
117 if ("POST".equals(rt.getReqMethod()))
119 Node node = (Node) bpelRequest.getRequestData();
120 Document reqDoc = node.getOwnerDocument();
121 sdncReqBody = Utils.genSdncReq(reqDoc, rt);
123 else if("PUT".equals(rt.getReqMethod())){
124 Node node = (Node) bpelRequest.getRequestData();
125 Document reqDoc = node.getOwnerDocument();
126 sdncReqBody = Utils.genSdncPutReq(reqDoc, rt);
128 long sdncStartTime = System.currentTimeMillis();
129 SDNCResponse sdncResp = getSdncResp(sdncReqBody, rt);
130 logger.debug ("Got the SDNC Response: {}", sdncResp.getSdncRespXml());
131 long bpelStartTime = System.currentTimeMillis();
132 sendRespToBpel(callbackUrl, sdncResp);
136 public SDNCResponse getSdncResp(String sdncReqBody, RequestTunables rt)
140 HttpURLConnection con = null;
141 DataOutputStream out = null;
142 BufferedReader in = null;
143 SDNCResponse sdncResp = new SDNCResponse(rt.getReqId());
144 StringBuilder response = new StringBuilder();
146 logger.info("{} :\n {} {}", MessageEnum.RA_SEND_REQUEST_SDNC.name(), rt.toString(), "SDNC");
147 logger.trace("SDNC Request Body:{} \n", sdncReqBody);
151 url = new URL(rt.getSdncUrl());
153 con = (HttpURLConnection) url.openConnection();
154 con.setConnectTimeout(Integer.parseInt(env.getProperty(Constants.SDNC_CONNECTTIME_PROP)));
155 con.setReadTimeout(Integer.parseInt(rt.getTimeout()));
156 con.setRequestProperty("Accept", "application/yang.data+xml"); //for response in xml
157 String userCredentials = CryptoUtils.decrypt(env.getProperty(Constants.SDNC_AUTH_PROP), env.getProperty(Constants.ENCRYPTION_KEY_PROP));
159 String basicAuth = "Basic " + DatatypeConverter.printBase64Binary(userCredentials.getBytes());
160 con.setRequestProperty ("Authorization", basicAuth);
161 con.setRequestMethod(rt.getReqMethod());
163 // Add request headers
164 if ("POST".equals(rt.getReqMethod()) || "PUT".equals(rt.getReqMethod()))
166 con.setRequestProperty("Content-type", "application/xml");
167 con.setRequestProperty("Content-length",String.valueOf(sdncReqBody.length()));
168 con.setDoOutput(true);
169 out = new DataOutputStream(con.getOutputStream());
170 out.writeBytes(sdncReqBody);
176 sdncResp.setRespCode(con.getResponseCode());
177 sdncResp.setRespMsg(con.getResponseMessage());
179 if (con.getResponseCode()>= 200 && con.getResponseCode()<=299) {
180 in = new BufferedReader(new InputStreamReader(con.getInputStream()));
182 //Not parsing the response -it contains a responseHdr section and data section
183 while ((inputLine = in.readLine()) != null) {
184 response.append(inputLine);
189 sdncResp.setSdncRespXml(response.toString());
190 logger.info("{} :\n {} {}", MessageEnum.RA_RESPONSE_FROM_SDNC.name(), sdncResp.toString(), "SDNC");
195 logger.error("{} {} {} {}", MessageEnum.RA_EXCEPTION_COMMUNICATE_SDNC.toString(), "SDNC",
196 ErrorCode.BusinessProcesssError.getValue(), "Exception processing request to SDNC", e);
198 sdncResp.setRespCode(HttpURLConnection.HTTP_INTERNAL_ERROR);
199 String respMsg = "Error processing request to SDNC. ";
200 StringBuilder sdncErrMsg = new StringBuilder();
202 if (e instanceof java.net.SocketTimeoutException )
204 sdncResp.setRespCode(HttpURLConnection.HTTP_CLIENT_TIMEOUT);
205 respMsg = "Request to SDNC timed out. ";
210 if (con.getResponseCode() != HttpURLConnection.HTTP_OK) //seen in SocketException connection reset
211 sdncResp.setRespCode(con.getResponseCode());
212 respMsg = respMsg + con.getResponseMessage() + ". ";
213 InputStream is = con.getErrorStream();
216 XPathFactory xpathFactory = XPathFactory.newInstance();
217 XPath xpath = xpathFactory.newXPath();
218 DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
219 dbf.setFeature (XMLConstants.FEATURE_SECURE_PROCESSING, true);
220 dbf.setFeature("http://xml.org/sax/features/external-general-entities", false);
221 dbf.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
225 db = dbf.newDocumentBuilder();
227 NodeList errors = (NodeList)xpath.evaluate("errors/error", doc, XPathConstants.NODESET);
228 for (int i = 0; i < errors.getLength(); i++)
230 Element error = (Element) errors.item(i);
233 eType = xpath.evaluate("error-type", error);
234 sdncErrMsg = new StringBuilder(". SDNC Returned-[error-type:" + eType);
235 } catch (Exception e3) {
236 logger.error("{} {} {} {} {} {}", MessageEnum.RA_EVALUATE_XPATH_ERROR.toString(), "error-type",
237 error.toString(), "SDNC", ErrorCode.DataError.getValue(), EXCEPTION_MSG, e3);
242 eTag = xpath.evaluate( "error-tag", error);
243 sdncErrMsg.append(", error-tag:").append(eTag);
244 } catch (Exception e3) {
245 logger.error("{} {} {} {} {} {}", MessageEnum.RA_EVALUATE_XPATH_ERROR.toString(), "error-tag",
246 error.toString(), "SDNC", ErrorCode.DataError.getValue(), EXCEPTION_MSG, e3);
251 eMsg = xpath.evaluate("error-message", error);
252 sdncErrMsg.append(", error-message:").append(eMsg).append("]");
253 } catch (Exception e3) {
254 logger.error("{} {} {} {} {} {}", MessageEnum.RA_EVALUATE_XPATH_ERROR.toString(), "error-message", error.toString(),
255 "SDNC", ErrorCode.DataError.getValue(), EXCEPTION_MSG, e3);
258 } catch (Exception e2) {
259 logger.error("{} {} {} {}", MessageEnum.RA_ANALYZE_ERROR_EXC.toString(), "SDNC",
260 ErrorCode.DataError.getValue(), "Exception while analyse error", e2);
263 } catch (Exception e1) {
264 logger.error("{} {} {} {}", MessageEnum.RA_ERROR_GET_RESPONSE_SDNC.toString(), "SDNC",
265 ErrorCode.BusinessProcesssError.getValue(), "Exception while get SDNC response", e1);
269 if (e.getMessage() != null) {
270 respMsg = respMsg + e.getMessage();
272 respMsg = respMsg + sdncErrMsg;
274 sdncResp.setRespMsg(respMsg);
276 logger.error("{} {} {} {}", MessageEnum.RA_EXCEPTION_COMMUNICATE_SDNC.toString(), "SDNC",
277 ErrorCode.AvailabilityError.getValue(), "Exception while communicate with SDNC", e);
289 public void sendRespToBpel(String bpelUrl, SDNCResponse sdncResp)
294 SDNCAdapterCallbackRequest cbReq = new SDNCAdapterCallbackRequest();
295 cbReq.setCallbackHeader(new CallbackHeader(sdncResp.getReqId(), Integer.toString(sdncResp.getRespCode()), sdncResp.getRespMsg()));
296 if (sdncResp.getSdncRespXml() != null)
298 cbReq.setRequestData(sdncResp.getSdncRespXml());
300 logger.info("{} :\n {} {}", MessageEnum.RA_CALLBACK_BPEL.name(), cbReq.toString(), CAMUNDA);
304 wsdlUrl = new URL (bpelUrl);
305 } catch (MalformedURLException e1) {
306 error = "Caught exception initializing Callback wsdl " + e1.getMessage();
307 logger.error("{} {} {} {}", MessageEnum.RA_INIT_CALLBACK_WSDL_ERR.toString(), CAMUNDA,
308 ErrorCode.DataError.getValue(), "Exception initializing Callback wsdl", e1);
312 SDNCCallbackAdapterService cbSvc = new SDNCCallbackAdapterService();
314 SDNCCallbackAdapterPortType cbPort = cbSvc.getSDNCCallbackAdapterSoapHttpPort();
316 BindingProvider bp = (BindingProvider)cbPort;
318 if(null != wsdlUrl) {
319 bp.getRequestContext().put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY, wsdlUrl.toExternalForm());
322 logger.debug("wsdlUrl is NULL:");
328 Map<String, Object> reqCtx = bp.getRequestContext();
329 Map<String, List<String>> headers = new HashMap<>();
330 String userCredentials = CryptoUtils.decrypt(env.getProperty(Constants.BPEL_AUTH_PROP), env.getProperty(Constants.ENCRYPTION_KEY_PROP));
332 String basicAuth = "Basic " + DatatypeConverter.printBase64Binary(userCredentials.getBytes());
333 reqCtx.put(MessageContext.HTTP_REQUEST_HEADERS, headers);
334 headers.put ("Authorization", Collections.singletonList(basicAuth));
336 catch (Exception e2) {
337 error = "Unable to set authorization in callback request " + e2.getMessage();
338 logger.error("{} {} {} {}", MessageEnum.RA_SET_CALLBACK_AUTH_EXC.toString(), CAMUNDA,
339 ErrorCode.BusinessProcesssError.getValue(),
340 "Exception - Unable to set authorization in callback request", e2);
344 logger.debug("Invoking Bpel Callback. BpelCallbackUrl:{}", bpelUrl);
345 cbPort.sdncAdapterCallback(cbReq);
350 error = "Error sending BpelCallback request" + e.getMessage();
351 logger.error("Error {} - {} - {}", ErrorCode.BusinessProcesssError.getValue(),
352 MessageEnum.RA_CALLBACK_BPEL_EXC.toString(), error, e);
354 logger.info(MessageEnum.RA_CALLBACK_BPEL_COMPLETE.name(), CAMUNDA);