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