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