57051e570ed5cdabbcf1e905b2d558447bec8ef5
[so.git] /
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  * 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.sdncrest;
26
27 import java.io.IOException;
28 import java.io.StringReader;
29 import java.net.HttpURLConnection;
30 import java.text.ParseException;
31 import java.util.ArrayList;
32 import java.util.List;
33
34 import javax.xml.XMLConstants;
35 import javax.xml.parsers.DocumentBuilderFactory;
36 import javax.xml.parsers.ParserConfigurationException;
37
38 import org.onap.so.adapters.sdncrest.SDNCErrorCommon;
39 import org.onap.so.adapters.sdncrest.SDNCResponseCommon;
40 import org.onap.so.adapters.sdncrest.SDNCServiceError;
41 import org.onap.so.adapters.sdncrest.SDNCServiceResponse;
42 import org.slf4j.Logger;
43 import org.slf4j.LoggerFactory;
44 import org.springframework.stereotype.Component;
45 import org.w3c.dom.Document;
46 import org.w3c.dom.Element;
47 import org.xml.sax.InputSource;
48 import org.xml.sax.SAXException;
49
50 /**
51  * SDNCConnector for "agnostic" API services.
52  */
53
54 @Component
55 public class SDNCServiceRequestConnector extends SDNCConnector {
56
57     private static final Logger logger = LoggerFactory.getLogger(SDNCServiceRequestConnector.class);
58         @Override
59         protected SDNCResponseCommon createResponseFromContent(int statusCode, String statusMessage,
60                         String responseContent, TypedRequestTunables rt) {
61                 try {
62                         return parseResponseContent(responseContent);
63                 } catch (ParseException e) {
64                         logger.error("Error occured:", e);
65                         return createErrorResponse(HttpURLConnection.HTTP_INTERNAL_ERROR, e.getMessage(), rt);
66                 }catch (Exception e) {
67                         logger.error("Error occured:", e);
68                         return createErrorResponse(HttpURLConnection.HTTP_INTERNAL_ERROR, e.getMessage(), rt);
69                 }
70         }
71
72         @Override
73         protected SDNCErrorCommon createErrorResponse(int statusCode, String errMsg,
74                         TypedRequestTunables rt) {
75                 return new SDNCServiceError(rt.getReqId(), String.valueOf(statusCode), errMsg, "Y");
76         }
77
78         /**
79          * Parses SDNC synchronous service response content or service notification content.
80          * If the content can be parsed and contains all required elements, then an object
81          * is returned.  The type of the returned object depends on the response code
82          * contained in the content.  For 2XX response codes, an SDNCServiceResponse is
83          * returned.  Otherwise, an SDNCServiceError is returned.  If the content cannot
84          * be parsed, or if the content does not contain all required elements, a parse
85          * exception is thrown.  This method performs no logging or alarming.
86          * @throws ParseException on error
87          */
88         public static SDNCResponseCommon parseResponseContent(String responseContent)
89                         throws ParseException,ParserConfigurationException, SAXException, IOException{
90
91                         // Note: this document builder is not namespace-aware, so namespaces are ignored.
92                         DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
93                         documentBuilderFactory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
94                     documentBuilderFactory.setFeature("http://xml.org/sax/features/external-general-entities", false);
95                     documentBuilderFactory.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
96                         InputSource source = new InputSource(new StringReader(responseContent));
97                         Document doc = documentBuilderFactory.newDocumentBuilder().parse(source);
98
99                         // Find the configuration-response-common child under the root element.
100                         // The root element is expected to be an "output" element, but we don't really care.
101
102                         Element root = doc.getDocumentElement();
103                         Element configurationResponseCommon = null;
104
105                         for (Element child : SDNCAdapterUtils.childElements(root)) {
106                                 if ("configuration-response-common".equals(child.getNodeName())) {
107                                         configurationResponseCommon = child;
108                                         break;
109                                 }
110                         }
111
112                         if (configurationResponseCommon == null) {
113                                 throw new ParseException("No configuration-response-common element in SDNC response", 0);
114                         }
115
116                         // Process the children of configuration-response-common.
117
118                         String responseCode = null;
119                         String responseMessage = null;
120                         String svcRequestId = null;
121                         String ackFinalIndicator = null;
122                         List<Element> responseParameters = new ArrayList<>();
123
124                         for (Element child : SDNCAdapterUtils.childElements(configurationResponseCommon)) {
125                                 if ("response-code".equals(child.getNodeName())) {
126                                         responseCode = child.getTextContent();
127                                 } else if ("response-message".equals(child.getNodeName())) {
128                                         responseMessage = child.getTextContent();
129                                 } else if ("svc-request-id".equals(child.getNodeName())) {
130                                         svcRequestId = child.getTextContent();
131                                 } else if ("ack-final-indicator".equals(child.getNodeName())) {
132                                         ackFinalIndicator = child.getTextContent();
133                                 } else if ("response-parameters".equals(child.getNodeName())) {
134                     responseParameters.add(child);
135                                 }
136                         }
137
138                         // svc-request-id is mandatory.
139
140                         if (svcRequestId == null || svcRequestId.isEmpty()) {
141                                 throw new ParseException("No svc-request-id in SDNC response", 0);
142                         }
143
144                         // response-code is mandatory.
145
146                         if (responseCode == null || responseCode.isEmpty()) {
147                                 throw new ParseException("No response-code in SDNC response", 0);
148                         }
149
150                         // ack-final-indicator is optional: default to "Y".
151
152                         if (ackFinalIndicator == null || ackFinalIndicator.trim().isEmpty()) {
153                                 ackFinalIndicator = "Y";
154                         }
155
156                         if (!"Y".equals(ackFinalIndicator) && !"N".equals(ackFinalIndicator)) {
157                                 throw new ParseException("Invalid ack-final-indicator in SDNC response: '" + ackFinalIndicator + "'", 0);
158                         }
159
160                         // response-message is optional.  If the value is empty, omit it from the response object.
161
162                         if (responseMessage != null && responseMessage.isEmpty()) {
163                                 responseMessage = null;
164                         }
165
166                         // If the response code in the message from SDNC was not 2XX, return SDNCServiceError.
167
168                         if (!responseCode.matches("2[0-9][0-9]") && !("0").equals(responseCode)) {
169                                 // Not a 2XX response.  Return SDNCServiceError.
170                                 return new SDNCServiceError(svcRequestId, responseCode, responseMessage, ackFinalIndicator);
171                         }
172
173                         // Create a success response object.
174
175                         SDNCServiceResponse response = new SDNCServiceResponse(svcRequestId,
176                                 responseCode, responseMessage, ackFinalIndicator);
177
178             // Process any response-parameters that might be present.
179
180             for (Element element : responseParameters) {
181                 String tagName = null;
182                 String tagValue = null;
183
184                 for (Element child : SDNCAdapterUtils.childElements(element)) {
185                     if ("tag-name".equals(child.getNodeName())) {
186                         tagName = child.getTextContent();
187                     } else if ("tag-value".equals(child.getNodeName())) {
188                         tagValue = child.getTextContent();
189                     }
190                 }
191
192                 // tag-name is mandatory
193
194                 if (tagName == null) {
195                     throw new ParseException("Missing tag-name in SDNC response parameter", 0);
196                 }
197
198                 // tag-value is optional.  If absent, make it an empty string so we don't
199                 // end up with null values in the parameter map.
200
201                 if (tagValue == null) {
202                     tagValue = "";
203                 }
204
205                 response.addParam(tagName, tagValue);
206             }
207
208                         return response;
209                 
210         }
211 }