Merge "Add code to allocate server ports"
diff --git a/policy-endpoints/src/main/java/org/onap/policy/common/endpoints/http/client/internal/JerseyClient.java b/policy-endpoints/src/main/java/org/onap/policy/common/endpoints/http/client/internal/JerseyClient.java
index ca0611c..d4ccc49 100644
--- a/policy-endpoints/src/main/java/org/onap/policy/common/endpoints/http/client/internal/JerseyClient.java
+++ b/policy-endpoints/src/main/java/org/onap/policy/common/endpoints/http/client/internal/JerseyClient.java
@@ -8,9 +8,9 @@
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
- * 
+ *
  *      http://www.apache.org/licenses/LICENSE-2.0
- * 
+ *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -25,13 +25,9 @@
 import java.security.KeyManagementException;
 import java.security.NoSuchAlgorithmException;
 import java.security.SecureRandom;
-import java.security.cert.CertificateException;
-import java.security.cert.X509Certificate;
 import java.util.Map;
 import java.util.Map.Entry;
 import javax.net.ssl.SSLContext;
-import javax.net.ssl.TrustManager;
-import javax.net.ssl.X509TrustManager;
 import javax.ws.rs.client.Client;
 import javax.ws.rs.client.ClientBuilder;
 import javax.ws.rs.client.Entity;
@@ -42,6 +38,7 @@
 import org.onap.policy.common.endpoints.event.comm.bus.internal.BusTopicParams;
 import org.onap.policy.common.endpoints.http.client.HttpClient;
 import org.onap.policy.common.gson.annotation.GsonJsonIgnore;
+import org.onap.policy.common.utils.network.NetworkUtil;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -54,7 +51,7 @@
      * Logger.
      */
     private static Logger logger = LoggerFactory.getLogger(JerseyClient.class);
-    
+
     protected static final String JERSEY_DEFAULT_SERIALIZATION_PROVIDER =
                     "com.fasterxml.jackson.jaxrs.json.JacksonJaxbJsonProvider";
 
@@ -74,11 +71,11 @@
 
     /**
      * Constructor.
-     * 
+     *
      * <p>name the name https is it https or not selfSignedCerts are there self signed certs
      * hostname the hostname port port being used basePath base context userName user
      * password password
-     * 
+     *
      * @param busTopicParams Input parameters object
      * @throws KeyManagementException key exception
      * @throws NoSuchAlgorithmException no algorithm exception
@@ -116,25 +113,7 @@
             ClientBuilder clientBuilder;
             SSLContext sslContext = SSLContext.getInstance("TLSv1.2");
             if (this.selfSignedCerts) {
-                sslContext.init(null, new TrustManager[] {new X509TrustManager() {
-                    @Override
-                    public void checkClientTrusted(X509Certificate[] chain, String authType)
-                            throws CertificateException {
-                        // always trusted
-                    }
-
-                    @Override
-                    public void checkServerTrusted(X509Certificate[] chain, String authType)
-                            throws CertificateException {
-                        // always trusted
-                    }
-
-                    @Override
-                    public X509Certificate[] getAcceptedIssuers() {
-                        return new X509Certificate[0];
-                    }
-
-                } }, new SecureRandom());
+                sslContext.init(null, NetworkUtil.getAlwaysTrustingManager(), new SecureRandom());
                 clientBuilder =
                         ClientBuilder.newBuilder().sslContext(sslContext).hostnameVerifier((host, session) -> true);
             } else {
@@ -153,7 +132,7 @@
         }
 
         registerSerProviders(busTopicParams.getSerializationProvider());
-        
+
         this.client.property(ClientProperties.METAINF_SERVICES_LOOKUP_DISABLE, "true");
 
         this.baseUrl = tmpBaseUrl.append(this.hostname).append(":").append(this.port).append("/")
@@ -162,7 +141,7 @@
 
     /**
      * Registers the serialization provider(s) with the client.
-     * 
+     *
      * @param serializationProvider comma-separated list of serialization providers
      * @throws ClassNotFoundException if the serialization provider cannot be found
      */
diff --git a/utils/src/main/java/org/onap/policy/common/utils/network/NetworkUtil.java b/utils/src/main/java/org/onap/policy/common/utils/network/NetworkUtil.java
index ae70ba4..aca34bb 100644
--- a/utils/src/main/java/org/onap/policy/common/utils/network/NetworkUtil.java
+++ b/utils/src/main/java/org/onap/policy/common/utils/network/NetworkUtil.java
@@ -1,8 +1,8 @@
-/*-
+/*
  * ============LICENSE_START=======================================================
  * ONAP
  * ================================================================================
- * Copyright (C) 2017-2018 AT&T Intellectual Property. All rights reserved.
+ * Copyright (C) 2017-2019 AT&T Intellectual Property. All rights reserved.
  * ================================================================================
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -23,9 +23,13 @@
 import java.io.IOException;
 import java.net.ConnectException;
 import java.net.InetAddress;
+import java.net.InetSocketAddress;
+import java.net.ServerSocket;
 import java.net.Socket;
 import java.net.UnknownHostException;
-
+import java.security.cert.X509Certificate;
+import javax.net.ssl.TrustManager;
+import javax.net.ssl.X509TrustManager;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -41,11 +45,80 @@
      */
     public static final String IPv4_WILDCARD_ADDRESS = "0.0.0.0";
 
+
+    /**
+     * A trust manager that always trusts certificates.
+     */
+    // @formatter:off
+    private static final TrustManager[] ALWAYS_TRUST_MANAGER = new TrustManager[] {
+        new X509TrustManager() {
+
+            @Override
+            public X509Certificate[] getAcceptedIssuers() {
+                return new X509Certificate[0];
+            }
+
+            @Override
+            public void checkClientTrusted(final java.security.cert.X509Certificate[] certs,
+                            final String authType) {}
+
+            @Override
+            public void checkServerTrusted(final java.security.cert.X509Certificate[] certs,
+                            final String authType) {}
+        }
+    };
+    // @formatter:on
+
     private NetworkUtil() {
         // Empty constructor
     }
 
     /**
+     * Allocates an available port on which a server may listen.
+     *
+     * @return an available port
+     * @throws IOException if a socket cannot be created
+     */
+    public static int allocPort() throws IOException {
+        return allocPort((InetSocketAddress) null);
+    }
+
+    /**
+     * Allocates an available port on which a server may listen.
+     *
+     * @param hostName the server's host name
+     * @return an available port
+     * @throws IOException if a socket cannot be created
+     */
+    public static int allocPort(String hostName) throws IOException {
+        return allocPort(new InetSocketAddress(hostName, 0));
+    }
+
+    /**
+     * Allocates an available port on which a server may listen.
+     *
+     * @param hostAddr the server's host address on which to listen
+     * @return an available port
+     * @throws IOException if a socket cannot be created
+     */
+    public static int allocPort(InetSocketAddress hostAddr) throws IOException {
+        try (ServerSocket socket = new ServerSocket()) {
+            socket.bind(hostAddr);
+
+            return socket.getLocalPort();
+        }
+    }
+
+    /**
+     * Gets a trust manager that accepts all certificates.
+     *
+     * @return a trust manager that accepts all certificates
+     */
+    public static TrustManager[] getAlwaysTrustingManager() {
+        return ALWAYS_TRUST_MANAGER;
+    }
+
+    /**
      * try to connect to $host:$port $retries times while we are getting connection failures.
      *
      * @param host host
diff --git a/utils/src/test/java/org/onap/policy/common/utils/network/NetworkUtilTest.java b/utils/src/test/java/org/onap/policy/common/utils/network/NetworkUtilTest.java
index 6dd09d6..c29da2c 100644
--- a/utils/src/test/java/org/onap/policy/common/utils/network/NetworkUtilTest.java
+++ b/utils/src/test/java/org/onap/policy/common/utils/network/NetworkUtilTest.java
@@ -1,15 +1,15 @@
-/*-
+/*
  * ============LICENSE_START=======================================================
  * policy-utils
  * ================================================================================
- * Copyright (C) 2018 AT&T Intellectual Property. All rights reserved.
+ * Copyright (C) 2018-2019 AT&T Intellectual Property. All rights reserved.
  * ================================================================================
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
- * 
+ *
  *      http://www.apache.org/licenses/LICENSE-2.0
- * 
+ *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -20,21 +20,95 @@
 
 package org.onap.policy.common.utils.network;
 
+import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
 
 import java.io.IOException;
-
+import java.net.InetSocketAddress;
+import java.net.ServerSocket;
+import java.net.Socket;
+import javax.net.ssl.TrustManager;
+import javax.net.ssl.X509TrustManager;
 import org.junit.Test;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 public class NetworkUtilTest {
+    protected static Logger logger = LoggerFactory.getLogger(NetworkUtilTest.class);
+
+    private static final String LOCALHOST = "localhost";
 
     @Test
     public void test() throws InterruptedException, IOException {
         assertNotNull(NetworkUtil.IPv4_WILDCARD_ADDRESS);
-        assertFalse(NetworkUtil.isTcpPortOpen("localhost", 8180, 1, 5));
+        assertFalse(NetworkUtil.isTcpPortOpen(LOCALHOST, NetworkUtil.allocPort(), 1, 5));
         assertNotNull(NetworkUtil.getHostname());
         assertNotNull(NetworkUtil.getHostIp());
     }
 
+    @Test
+    public void testAlwaysTrustManager() throws Exception {
+        TrustManager[] mgrarr = NetworkUtil.getAlwaysTrustingManager();
+        assertEquals(1, mgrarr.length);
+        assertTrue(mgrarr[0] instanceof X509TrustManager);
+
+        X509TrustManager mgr = (X509TrustManager) mgrarr[0];
+        assertNotNull(mgr.getAcceptedIssuers());
+        assertEquals(0, mgr.getAcceptedIssuers().length);
+
+        // these should not throw exceptions
+        mgr.checkClientTrusted(null, null);
+        mgr.checkServerTrusted(null, null);
+    }
+
+    @Test
+    public void testAllocPort_testAllocPortString__testAllocPortInetSocketAddress() throws Exception {
+        // allocate wild-card port
+        int wildCardPort = NetworkUtil.allocPort();
+        assertTrue(wildCardPort != 0);
+
+        // verify that we can listen on the port
+        try (ServerSocket wildSocket = new ServerSocket(wildCardPort)) {
+            new Accepter(wildSocket).start();
+            assertTrue(NetworkUtil.isTcpPortOpen(LOCALHOST, wildCardPort, 5, 1000L));
+        }
+
+
+        // allocate port using host name
+        int localPort = NetworkUtil.allocPort(LOCALHOST);
+        assertTrue(localPort != 0);
+
+        // the OS should have allocated a new port, even though the first has been closed
+        assertTrue(localPort != wildCardPort);
+
+        try (ServerSocket localSocket = new ServerSocket()) {
+            localSocket.bind(new InetSocketAddress(LOCALHOST, localPort));
+            new Accepter(localSocket).start();
+            assertTrue(NetworkUtil.isTcpPortOpen(LOCALHOST, localPort, 5, 1000L));
+        }
+    }
+
+    /**
+     * Thread that accepts a connection on a socket.
+     */
+    private static class Accepter extends Thread {
+        private ServerSocket socket;
+
+        public Accepter(ServerSocket socket) {
+            this.socket = socket;
+            setDaemon(true);
+        }
+
+        @Override
+        public void run() {
+            try (Socket server = socket.accept()) {
+                // do nothing
+
+            } catch (IOException e) {
+                logger.error("socket not accepted", e);
+            }
+        }
+    }
 }