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;
46 import org.onap.policy.apex.model.basicmodel.concepts.ApexRuntimeException;
47 import org.onap.policy.common.utils.network.NetworkUtil;
48 import org.slf4j.ext.XLogger;
49 import org.slf4j.ext.XLoggerFactory;
50 import org.w3c.dom.Document;
51 import org.w3c.dom.Node;
52 import org.w3c.dom.NodeList;
53 import org.xml.sax.InputSource;
56 * The Class WebClient act as rest client for BBS usecase.
58 public class WebClient {
60 private static final XLogger LOGGER = XLoggerFactory.getXLogger(WebClient.class);
62 // Duplicated string constants
63 private static final String BBS_POLICY = "BBS Policy";
65 //Features to prevent XXE injection
66 private static final String XML_DISALLOW_DOCTYPE_FEATURE = "http://apache.org/xml/features/disallow-doctype-decl";
67 private static final String XML_EXTERNAL_ENTITY_FEATURE = "http://xml.org/sax/features/external-general-entities";
70 * Send simple https rest request.
72 * @param requestUrl url
73 * @param requestMethod method eg POST/GET/PUT
74 * @param outputStr Data
75 * @param username Simple Username
76 * @param pass Simple password
77 * @param contentType http content type
78 * @return String response message
80 public String httpRequest(String requestUrl, String requestMethod, String outputStr, String username, String pass,
83 StringBuilder builder = new StringBuilder();
85 LOGGER.info("httpsRequest starts {} method {}", requestUrl, requestMethod);
86 disableCertificateValidation();
88 URL url = new URL(requestUrl);
89 HttpURLConnection httpUrlConn = (HttpURLConnection) url.openConnection();
91 httpUrlConn.setDoOutput(true);
92 httpUrlConn.setDoInput(true);
93 httpUrlConn.setUseCaches(false);
95 if ((username != null) && (pass != null)) {
96 httpUrlConn.setRequestProperty("Authorization", getAuth(username, pass));
98 LOGGER.warn("Authorization information missing");
101 httpUrlConn.setRequestProperty("Content-Type", contentType);
102 httpUrlConn.setRequestProperty("Accept", contentType);
103 httpUrlConn.setRequestProperty("X-FromAppId", BBS_POLICY);
104 httpUrlConn.setRequestProperty("X-TransactionId", BBS_POLICY);
105 httpUrlConn.setRequestMethod(requestMethod);
107 if ("GET".equalsIgnoreCase(requestMethod)) {
108 httpUrlConn.connect();
111 if (null != outputStr) {
112 OutputStream outputStream = httpUrlConn.getOutputStream();
113 outputStream.write(outputStr.getBytes(StandardCharsets.UTF_8));
114 outputStream.close();
117 try (BufferedReader bufferedReader = new BufferedReader(
118 new InputStreamReader(httpUrlConn.getInputStream(), StandardCharsets.UTF_8))) {
120 while ((str = bufferedReader.readLine()) != null) {
123 httpUrlConn.disconnect();
124 result = builder.toString();
126 LOGGER.info("httpsRequest success");
127 } catch (Exception ce) {
128 LOGGER.error("httpsRequest Exception", ce);
134 * Pretty print xml string.
136 * @param xml Input string
137 * @param indent Indent number
138 * @return Indented xml string
140 public String toPrettyString(String xml, int indent) {
142 try (ByteArrayInputStream br = new ByteArrayInputStream(xml.getBytes(StandardCharsets.UTF_8))) {
144 DocumentBuilderFactory df = DocumentBuilderFactory.newInstance();
145 df.setFeature(XML_DISALLOW_DOCTYPE_FEATURE, true);
146 df.setFeature(XML_EXTERNAL_ENTITY_FEATURE, false);
147 Document document = df.newDocumentBuilder().parse(new InputSource(br));
149 document.normalize();
150 XPath path = XPathFactory.newInstance().newXPath();
151 NodeList nodeList = (NodeList) path
152 .evaluate("//text()[normalize-space()='']", document, XPathConstants.NODESET);
154 for (int i = 0; i < nodeList.getLength(); ++i) {
155 Node node = nodeList.item(i);
156 node.getParentNode().removeChild(node);
159 TransformerFactory transformerFactory = TransformerFactory.newInstance();
160 transformerFactory.setAttribute("indent-number", indent);
161 Transformer transformer = transformerFactory.newTransformer();
162 transformer.setOutputProperty(OutputKeys.ENCODING, StandardCharsets.UTF_8.name());
163 transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
164 transformer.setOutputProperty(OutputKeys.INDENT, "yes");
166 StringWriter stringWriter = new StringWriter();
167 transformer.transform(new DOMSource(document), new StreamResult(stringWriter));
168 return stringWriter.toString();
170 } catch (Exception e) {
171 throw new ApexRuntimeException("Convert to Pretty string failed", e);
176 * Disable ssl verification.
178 private static void disableCertificateValidation() {
180 TrustManager[] trustAllCerts = NetworkUtil.getAlwaysTrustingManager();
182 SSLContext sc = SSLContext.getInstance("TLS");
183 sc.init(null, trustAllCerts, new java.security.SecureRandom());
184 HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
185 HttpsURLConnection.setDefaultHostnameVerifier((String hostname, SSLSession session) -> {
186 if (!hostname.equalsIgnoreCase(session.getPeerHost())) {
187 LOGGER.warn("Warning: URL host \"{}\" is different to SSLSession host \"{}\".", hostname,
188 session.getPeerHost());
193 } catch (Exception e) {
194 LOGGER.error("certificate validation Exception", e);
199 * Return Basic Authentication String.
201 * @param userName UserName
202 * @param password PassWord
203 * @return Basic Authentication
205 private String getAuth(String userName, String password) {
206 String userCredentials = userName + ":" + password;
207 return ("Basic " + Base64.getEncoder().encodeToString(userCredentials.getBytes(StandardCharsets.UTF_8)));