Merge "Sonar Security vulnerabilities fix"
diff --git a/core/core-infrastructure/src/main/java/org/onap/policy/apex/core/infrastructure/xml/XPathReader.java b/core/core-infrastructure/src/main/java/org/onap/policy/apex/core/infrastructure/xml/XPathReader.java
index 08046c9..a9c57f3 100644
--- a/core/core-infrastructure/src/main/java/org/onap/policy/apex/core/infrastructure/xml/XPathReader.java
+++ b/core/core-infrastructure/src/main/java/org/onap/policy/apex/core/infrastructure/xml/XPathReader.java
@@ -1,6 +1,7 @@
 /*-
  * ============LICENSE_START=======================================================
  *  Copyright (C) 2016-2018 Ericsson. All rights reserved.
+ *  Modifications Copyright (C) 2020 Nordix Foundation.
  * ================================================================================
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -22,6 +23,7 @@
 
 import java.io.InputStream;
 
+import javax.xml.XMLConstants;
 import javax.xml.namespace.QName;
 import javax.xml.parsers.DocumentBuilderFactory;
 import javax.xml.xpath.XPath;
@@ -39,6 +41,7 @@
  * @author Sajeevan Achuthan (sajeevan.achuthan@ericsson.com)
  */
 public class XPathReader {
+
     // Logger for this class
     private static final XLogger LOGGER = XLoggerFactory.getXLogger(XPathReader.class);
 
@@ -73,18 +76,17 @@
     private void init() {
         try {
             LOGGER.info("Initializing XPath reader");
+            DocumentBuilderFactory df = DocumentBuilderFactory.newInstance();
+            df.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
 
             // Check if this is operating on a file
             if (xmlFileName != null) {
-                xmlDocument = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(xmlFileName);
-            }
-            // Check if this is operating on a stream
-            else if (xmlStream != null) {
-                xmlDocument = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(xmlStream);
-
-            }
-            // We have an error
-            else {
+                xmlDocument = df.newDocumentBuilder().parse(xmlFileName);
+            } else if (xmlStream != null) {
+                // Check if this is operating on a stream
+                xmlDocument = df.newDocumentBuilder().parse(xmlStream);
+            } else {
+                // We have an error
                 LOGGER.error("XPath reader not initialized with either a file or a stream");
                 return;
             }
diff --git a/examples/examples-onap-bbs/src/main/java/org/onap/policy/apex/examples/bbs/WebClient.java b/examples/examples-onap-bbs/src/main/java/org/onap/policy/apex/examples/bbs/WebClient.java
index e4186f1..edaff6b 100644
--- a/examples/examples-onap-bbs/src/main/java/org/onap/policy/apex/examples/bbs/WebClient.java
+++ b/examples/examples-onap-bbs/src/main/java/org/onap/policy/apex/examples/bbs/WebClient.java
@@ -1,7 +1,7 @@
 /*-
  * ============LICENSE_START=======================================================
  *  Copyright (C) 2019 Huawei. All rights reserved.
- *  Modifications Copyright (C) 2019 Nordix Foundation.
+ *  Modifications Copyright (C) 2019-2020 Nordix Foundation.
  * ================================================================================
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -32,7 +32,9 @@
 import java.util.Base64;
 import javax.net.ssl.HttpsURLConnection;
 import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLSession;
 import javax.net.ssl.TrustManager;
+import javax.xml.XMLConstants;
 import javax.xml.parsers.DocumentBuilderFactory;
 import javax.xml.transform.OutputKeys;
 import javax.xml.transform.Transformer;
@@ -56,6 +58,7 @@
  * The Class WebClient act as rest client for BBS usecase.
  */
 public class WebClient {
+
     private static final XLogger LOGGER = XLoggerFactory.getXLogger(WebClient.class);
 
     // Duplicated string constants
@@ -64,20 +67,20 @@
     /**
      * Send simple https rest request.
      *
-     * @param requestUrl url
+     * @param requestUrl    url
      * @param requestMethod method eg POST/GET/PUT
-     * @param outputStr Data
-     * @param username Simple Username
-     * @param pass Simple password
-     * @param contentType http content type
+     * @param outputStr     Data
+     * @param username      Simple Username
+     * @param pass          Simple password
+     * @param contentType   http content type
      * @return String response message
      */
     public String httpRequest(String requestUrl, String requestMethod, String outputStr, String username, String pass,
-            String contentType) {
+        String contentType) {
         String result = "";
         StringBuilder builder = new StringBuilder();
         try {
-            LOGGER.info("httpsRequest starts " + requestUrl + " method " + requestMethod);
+            LOGGER.info("httpsRequest starts {} method {}", requestUrl, requestMethod);
             disableCertificateValidation();
 
             URL url = new URL(requestUrl);
@@ -109,8 +112,8 @@
                 outputStream.close();
             }
 
-            try (BufferedReader bufferedReader =
-                    new BufferedReader(new InputStreamReader(httpUrlConn.getInputStream(), StandardCharsets.UTF_8))) {
+            try (BufferedReader bufferedReader = new BufferedReader(
+                new InputStreamReader(httpUrlConn.getInputStream(), StandardCharsets.UTF_8))) {
                 String str;
                 while ((str = bufferedReader.readLine()) != null) {
                     builder.append(str);
@@ -118,9 +121,9 @@
                 httpUrlConn.disconnect();
                 result = builder.toString();
             }
-            LOGGER.info("httpsRequest success ");
+            LOGGER.info("httpsRequest success");
         } catch (Exception ce) {
-            LOGGER.error("httpsRequest Exception " + ce);
+            LOGGER.error("httpsRequest Exception", ce);
         }
         return result;
     }
@@ -128,20 +131,22 @@
     /**
      * Pretty print xml string.
      *
-     * @param xml Input string
+     * @param xml    Input string
      * @param indent Indent number
      * @return Indented xml string
      */
     public String toPrettyString(String xml, int indent) {
         try {
             try (ByteArrayInputStream br = new ByteArrayInputStream(xml.getBytes(StandardCharsets.UTF_8))) {
-                Document document =
-                        DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(new InputSource(br));
+
+                DocumentBuilderFactory df = DocumentBuilderFactory.newInstance();
+                df.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
+                Document document = df.newDocumentBuilder().parse(new InputSource(br));
 
                 document.normalize();
                 XPath path = XPathFactory.newInstance().newXPath();
-                NodeList nodeList =
-                        (NodeList) path.evaluate("//text()[normalize-space()='']", document, XPathConstants.NODESET);
+                NodeList nodeList = (NodeList) path
+                    .evaluate("//text()[normalize-space()='']", document, XPathConstants.NODESET);
 
                 for (int i = 0; i < nodeList.getLength(); ++i) {
                     Node node = nodeList.item(i);
@@ -160,7 +165,7 @@
                 return stringWriter.toString();
             }
         } catch (Exception e) {
-            throw new ApexRuntimeException("pretiffication failed", e);
+            throw new ApexRuntimeException("Convert to Pretty string failed", e);
         }
     }
 
@@ -171,14 +176,19 @@
         try {
             TrustManager[] trustAllCerts = NetworkUtil.getAlwaysTrustingManager();
 
-            SSLContext sc = SSLContext.getInstance("SSL");
+            SSLContext sc = SSLContext.getInstance("TLS");
             sc.init(null, trustAllCerts, new java.security.SecureRandom());
             HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
-
-            HttpsURLConnection.setDefaultHostnameVerifier((hostname, session) -> true);
-
+            HttpsURLConnection.setDefaultHostnameVerifier((String hostname, SSLSession session) -> {
+                if (!hostname.equalsIgnoreCase(session.getPeerHost())) {
+                    LOGGER.warn("Warning: URL host \"{}\" is different to SSLSession host \"{}\".", hostname,
+                        session.getPeerHost());
+                    return false;
+                }
+                return true;
+            });
         } catch (Exception e) {
-            LOGGER.error("certificate validation Exception " + e);
+            LOGGER.error("certificate validation Exception", e);
         }
     }
 
diff --git a/model/basic-model/src/main/java/org/onap/policy/apex/model/basicmodel/handling/ApexModelWriter.java b/model/basic-model/src/main/java/org/onap/policy/apex/model/basicmodel/handling/ApexModelWriter.java
index 35c458e..8d6c01e 100644
--- a/model/basic-model/src/main/java/org/onap/policy/apex/model/basicmodel/handling/ApexModelWriter.java
+++ b/model/basic-model/src/main/java/org/onap/policy/apex/model/basicmodel/handling/ApexModelWriter.java
@@ -1,7 +1,7 @@
 /*-
  * ============LICENSE_START=======================================================
  *  Copyright (C) 2016-2018 Ericsson. All rights reserved.
- *  Modifications Copyright (C) 2019 Nordix Foundation.
+ *  Modifications Copyright (C) 2019-2020 Nordix Foundation.
  * ================================================================================
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -27,6 +27,7 @@
 import java.util.Set;
 import java.util.TreeSet;
 
+import javax.xml.XMLConstants;
 import javax.xml.bind.JAXBContext;
 import javax.xml.bind.JAXBException;
 import javax.xml.bind.Marshaller;
@@ -53,10 +54,11 @@
 /**
  * This class writes an Apex concept to an XML file or JSON file from a Java Apex Concept.
  *
- * @author John Keeney (john.keeney@ericsson.com)
  * @param <C> the type of Apex concept to write, must be a sub class of {@link AxConcept}
+ * @author John Keeney (john.keeney@ericsson.com)
  */
 public class ApexModelWriter<C extends AxConcept> {
+
     private static final String CONCEPT_MAY_NOT_BE_NULL = "concept may not be null";
     private static final String CONCEPT_WRITER_MAY_NOT_BE_NULL = "concept writer may not be null";
     private static final String CONCEPT_STREAM_MAY_NOT_BE_NULL = "concept stream may not be null";
@@ -87,15 +89,13 @@
         System.setProperty("javax.xml.bind.context.factory", "org.eclipse.persistence.jaxb.JAXBContextFactory");
 
         try {
-            final JAXBContext jaxbContext = JAXBContextFactory.createContext(new Class[]
-                { rootConceptClass }, null);
+            final JAXBContext jaxbContext = JAXBContextFactory.createContext(new Class[]{rootConceptClass}, null);
 
             // Set up the unmarshaller to carry out validation
             marshaller = jaxbContext.createMarshaller();
             marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
             marshaller.setEventHandler(new javax.xml.bind.helpers.DefaultValidationEventHandler());
         } catch (final JAXBException e) {
-            LOGGER.error("JAXB marshaller creation exception", e);
             throw new ApexModelException("JAXB marshaller creation exception", e);
         }
     }
@@ -133,14 +133,12 @@
                 marshaller.setProperty(MarshallerProperties.MEDIA_TYPE, MediaType.APPLICATION_JSON);
                 marshaller.setProperty(MarshallerProperties.JSON_INCLUDE_ROOT, true);
             } catch (final Exception e) {
-                LOGGER.warn("JAXB error setting marshaller for JSON output", e);
                 throw new ApexModelException("JAXB error setting marshaller for JSON output", e);
             }
         } else {
             try {
                 marshaller.setProperty(MarshallerProperties.MEDIA_TYPE, MediaType.APPLICATION_XML);
             } catch (final Exception e) {
-                LOGGER.warn("JAXB error setting marshaller for XML output", e);
                 throw new ApexModelException("JAXB error setting marshaller for XML output", e);
             }
         }
@@ -149,7 +147,7 @@
     /**
      * This method validates the Apex concept then writes it into a stream.
      *
-     * @param concept the concept to write
+     * @param concept           the concept to write
      * @param apexConceptStream the stream to write to
      * @throws ApexModelException on validation or writing exceptions
      */
@@ -163,7 +161,7 @@
     /**
      * This method validates the Apex concept then writes it into a writer.
      *
-     * @param concept the concept to write
+     * @param concept           the concept to write
      * @param apexConceptWriter the writer to write to
      * @throws ApexModelException on validation or writing exceptions
      */
@@ -176,9 +174,9 @@
             // Validate the concept first
             final AxValidationResult validationResult = concept.validate(new AxValidationResult());
             if (!validationResult.isValid()) {
-                String message = "Apex concept xml (" + concept.getKey().getId() + ") validation failed: "
-                                + validationResult.toString();
-                LOGGER.warn(message);
+                String message =
+                    "Apex concept xml (" + concept.getKey().getId() + ") validation failed: " + validationResult
+                        .toString();
                 throw new ApexModelException(message);
             }
         }
@@ -193,7 +191,7 @@
     /**
      * This method writes the Apex concept into a writer in XML format.
      *
-     * @param concept the concept to write
+     * @param concept           the concept to write
      * @param apexConceptWriter the writer to write to
      * @throws ApexModelException on validation or writing exceptions
      */
@@ -206,6 +204,7 @@
             // Write the concept into a DOM document, then transform to add CDATA fields and pretty
             // print, then write out the result
             final DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory.newInstance();
+            docBuilderFactory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
             final Document document = docBuilderFactory.newDocumentBuilder().newDocument();
 
             // Marshal the concept into the empty document.
@@ -215,10 +214,9 @@
 
             // Convert the cDataFieldSet into a space delimited string
             domTransformer.setOutputProperty(OutputKeys.CDATA_SECTION_ELEMENTS,
-                            cdataFieldSet.toString().replaceAll("[\\[\\]\\,]", " "));
+                cdataFieldSet.toString().replaceAll("[\\[\\]\\,]", " "));
             domTransformer.transform(new DOMSource(document), new StreamResult(apexConceptWriter));
         } catch (JAXBException | TransformerException | ParserConfigurationException e) {
-            LOGGER.warn("Unable to marshal Apex concept to XML", e);
             throw new ApexModelException("Unable to marshal Apex concept to XML", e);
         }
         LOGGER.debug("wrote Apex concept XML");
@@ -243,7 +241,7 @@
     /**
      * This method writes the Apex concept into a writer in JSON format.
      *
-     * @param concept the concept to write
+     * @param concept           the concept to write
      * @param apexConceptWriter the writer to write to
      * @throws ApexModelException on validation or writing exceptions
      */
@@ -255,7 +253,6 @@
         try {
             marshaller.marshal(concept, apexConceptWriter);
         } catch (final JAXBException e) {
-            LOGGER.warn("Unable to marshal Apex concept to JSON", e);
             throw new ApexModelException("Unable to marshal Apex concept to JSON", e);
         }
         LOGGER.debug("wrote Apex concept JSON");