2 * ============LICENSE_START=======================================================
3 * Copyright (C) 2019 Huawei. All rights reserved.
4 * Modifications Copyright (C) 2019-2020 Nordix Foundation.
5 * ================================================================================
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
18 * SPDX-License-Identifier: Apache-2.0
19 * ============LICENSE_END=========================================================
22 package org.onap.policy.apex.examples.bbs;
24 import java.io.BufferedReader;
25 import java.io.ByteArrayInputStream;
26 import java.io.InputStreamReader;
27 import java.io.OutputStream;
28 import java.io.StringWriter;
29 import java.net.HttpURLConnection;
31 import java.nio.charset.StandardCharsets;
32 import java.util.Base64;
33 import javax.net.ssl.HttpsURLConnection;
34 import javax.net.ssl.SSLContext;
35 import javax.net.ssl.SSLSession;
36 import javax.net.ssl.TrustManager;
37 import javax.xml.parsers.DocumentBuilderFactory;
38 import javax.xml.transform.OutputKeys;
39 import javax.xml.transform.Transformer;
40 import javax.xml.transform.TransformerFactory;
41 import javax.xml.transform.dom.DOMSource;
42 import javax.xml.transform.stream.StreamResult;
43 import javax.xml.xpath.XPath;
44 import javax.xml.xpath.XPathConstants;
45 import javax.xml.xpath.XPathFactory;
47 import org.onap.policy.apex.model.basicmodel.concepts.ApexRuntimeException;
48 import org.onap.policy.common.utils.network.NetworkUtil;
49 import org.slf4j.ext.XLogger;
50 import org.slf4j.ext.XLoggerFactory;
51 import org.w3c.dom.Document;
52 import org.w3c.dom.Node;
53 import org.w3c.dom.NodeList;
54 import org.xml.sax.InputSource;
57 * The Class WebClient act as rest client for BBS usecase.
59 public class WebClient {
61 private static final XLogger LOGGER = XLoggerFactory.getXLogger(WebClient.class);
63 // Duplicated string constants
64 private static final String BBS_POLICY = "BBS Policy";
66 //Features to prevent XXE injection
67 private static final String XML_DISALLOW_DOCTYPE_FEATURE = "http://apache.org/xml/features/disallow-doctype-decl";
68 private static final String XML_EXTERNAL_ENTITY_FEATURE = "http://xml.org/sax/features/external-general-entities";
71 * Send simple https rest request.
73 * @param requestUrl url
74 * @param requestMethod method eg POST/GET/PUT
75 * @param outputStr Data
76 * @param username Simple Username
77 * @param pass Simple password
78 * @param contentType http content type
79 * @return String response message
81 public String httpRequest(String requestUrl, String requestMethod, String outputStr, String username, String pass,
84 StringBuilder builder = new StringBuilder();
86 LOGGER.info("httpsRequest starts {} method {}", requestUrl, requestMethod);
87 disableCertificateValidation();
89 URL url = new URL(requestUrl);
90 HttpURLConnection httpUrlConn = (HttpURLConnection) url.openConnection();
92 httpUrlConn.setDoOutput(true);
93 httpUrlConn.setDoInput(true);
94 httpUrlConn.setUseCaches(false);
96 if ((username != null) && (pass != null)) {
97 httpUrlConn.setRequestProperty("Authorization", getAuth(username, pass));
99 LOGGER.warn("Authorization information missing");
102 httpUrlConn.setRequestProperty("Content-Type", contentType);
103 httpUrlConn.setRequestProperty("Accept", contentType);
104 httpUrlConn.setRequestProperty("X-FromAppId", BBS_POLICY);
105 httpUrlConn.setRequestProperty("X-TransactionId", BBS_POLICY);
106 httpUrlConn.setRequestMethod(requestMethod);
108 if ("GET".equalsIgnoreCase(requestMethod)) {
109 httpUrlConn.connect();
112 if (null != outputStr) {
113 OutputStream outputStream = httpUrlConn.getOutputStream();
114 outputStream.write(outputStr.getBytes(StandardCharsets.UTF_8));
115 outputStream.close();
118 try (BufferedReader bufferedReader = new BufferedReader(
119 new InputStreamReader(httpUrlConn.getInputStream(), StandardCharsets.UTF_8))) {
121 while ((str = bufferedReader.readLine()) != null) {
124 httpUrlConn.disconnect();
125 result = builder.toString();
127 LOGGER.info("httpsRequest success");
128 } catch (Exception ce) {
129 LOGGER.error("httpsRequest Exception", ce);
135 * Pretty print xml string.
137 * @param xml Input string
138 * @param indent Indent number
139 * @return Indented xml string
141 public String toPrettyString(String xml, int indent) {
143 try (ByteArrayInputStream br = new ByteArrayInputStream(xml.getBytes(StandardCharsets.UTF_8))) {
145 DocumentBuilderFactory df = DocumentBuilderFactory.newInstance();
146 df.setFeature(XML_DISALLOW_DOCTYPE_FEATURE, true);
147 df.setFeature(XML_EXTERNAL_ENTITY_FEATURE, false);
148 Document document = df.newDocumentBuilder().parse(new InputSource(br));
150 document.normalize();
151 XPath path = XPathFactory.newInstance().newXPath();
152 NodeList nodeList = (NodeList) path
153 .evaluate("//text()[normalize-space()='']", document, XPathConstants.NODESET);
155 for (int i = 0; i < nodeList.getLength(); ++i) {
156 Node node = nodeList.item(i);
157 node.getParentNode().removeChild(node);
160 TransformerFactory transformerFactory = TransformerFactory.newInstance();
161 transformerFactory.setAttribute("indent-number", indent);
162 Transformer transformer = transformerFactory.newTransformer();
163 transformer.setOutputProperty(OutputKeys.ENCODING, StandardCharsets.UTF_8.name());
164 transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
165 transformer.setOutputProperty(OutputKeys.INDENT, "yes");
167 StringWriter stringWriter = new StringWriter();
168 transformer.transform(new DOMSource(document), new StreamResult(stringWriter));
169 return stringWriter.toString();
171 } catch (Exception e) {
172 throw new ApexRuntimeException("Convert to Pretty string failed", e);
177 * Disable ssl verification.
179 private static void disableCertificateValidation() {
181 TrustManager[] trustAllCerts = NetworkUtil.getAlwaysTrustingManager();
183 SSLContext sc = SSLContext.getInstance("TLS");
184 sc.init(null, trustAllCerts, new java.security.SecureRandom());
185 HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
186 HttpsURLConnection.setDefaultHostnameVerifier((String hostname, SSLSession session) -> {
187 if (!hostname.equalsIgnoreCase(session.getPeerHost())) {
188 LOGGER.warn("Warning: URL host \"{}\" is different to SSLSession host \"{}\".", hostname,
189 session.getPeerHost());
194 } catch (Exception e) {
195 LOGGER.error("certificate validation Exception", e);
200 * Return Basic Authentication String.
202 * @param userName UserName
203 * @param password PassWord
204 * @return Basic Authentication
206 private String getAuth(String userName, String password) {
207 String userCredentials = userName + ":" + password;
208 return ("Basic " + Base64.getEncoder().encodeToString(userCredentials.getBytes(StandardCharsets.UTF_8)));