Upgrading rest sb protocol with jersey 2.22.2, implementing different connection test

Change-Id: Iba64847b535826f24ae4dc0ab3454a31328406ac
diff --git a/protocols/rest/ctl/src/main/java/org/onosproject/protocol/rest/ctl/RestSBControllerImpl.java b/protocols/rest/ctl/src/main/java/org/onosproject/protocol/rest/ctl/RestSBControllerImpl.java
index c787fb9..d813221 100644
--- a/protocols/rest/ctl/src/main/java/org/onosproject/protocol/rest/ctl/RestSBControllerImpl.java
+++ b/protocols/rest/ctl/src/main/java/org/onosproject/protocol/rest/ctl/RestSBControllerImpl.java
@@ -36,18 +36,24 @@
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+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;
 import javax.ws.rs.client.WebTarget;
 import javax.ws.rs.core.MediaType;
 import javax.ws.rs.core.Response;
+import java.io.ByteArrayInputStream;
 import java.io.IOException;
 import java.io.InputStream;
 import java.nio.charset.StandardCharsets;
 import java.security.KeyManagementException;
 import java.security.KeyStoreException;
 import java.security.NoSuchAlgorithmException;
+import java.security.cert.CertificateException;
+import java.security.cert.X509Certificate;
 import java.util.Base64;
 import java.util.Map;
 import java.util.concurrent.ConcurrentHashMap;
@@ -73,16 +79,16 @@
     private static final String BASIC_AUTH_PREFIX = "Basic ";
 
     private final Map<DeviceId, RestSBDevice> deviceMap = new ConcurrentHashMap<>();
-    Client client;
+    private final Map<DeviceId, Client> clientMap = new ConcurrentHashMap<>();
 
     @Activate
     public void activate() {
-        client = ClientBuilder.newClient();
         log.info("Started");
     }
 
     @Deactivate
     public void deactivate() {
+        clientMap.clear();
         deviceMap.clear();
         log.info("Stopped");
     }
@@ -105,11 +111,24 @@
 
     @Override
     public void addDevice(RestSBDevice device) {
-        deviceMap.put(device.deviceId(), device);
+        if (!deviceMap.containsKey(device.deviceId())) {
+            Client client = ignoreSslClient();
+            if (device.username() != null) {
+                String username = device.username();
+                String password = device.password() == null ? "" : device.password();
+                authenticate(client, username, password);
+            }
+            clientMap.put(device.deviceId(), client);
+            deviceMap.put(device.deviceId(), device);
+        } else {
+            log.warn("Trying to add a device that is already existing {}", device.deviceId());
+        }
+
     }
 
     @Override
     public void removeDevice(DeviceId deviceId) {
+        clientMap.remove(deviceId);
         deviceMap.remove(deviceId);
     }
 
@@ -169,7 +188,8 @@
 
         Response s = wt.request(type).get();
         if (checkReply(s)) {
-            return (InputStream) s.getEntity();
+            return new ByteArrayInputStream(wt.request(type)
+                    .get(String.class).getBytes(StandardCharsets.UTF_8));
         }
         return null;
     }
@@ -219,15 +239,13 @@
         return checkReply(response);
     }
 
+    private void authenticate(Client client, String username, String password) {
+        client.register(HttpAuthenticationFeature.basic(username, password));
+    }
+
     private WebTarget getWebTarget(DeviceId device, String request) {
         log.debug("Sending request to URL {} ", getUrlString(device, request));
-        WebTarget wt = client.target(getUrlString(device, request));
-        if (deviceMap.containsKey(device) && deviceMap.get(device).username() != null) {
-            client.register(HttpAuthenticationFeature.basic(deviceMap.get(device).username(),
-                                                     deviceMap.get(device).password() == null ?
-                                                             "" : deviceMap.get(device).password()));
-        }
-        return wt;
+        return clientMap.get(device).target(getUrlString(device, request));
     }
 
     //FIXME security issue: this trusts every SSL certificate, even if is self-signed. Also deprecated methods.
@@ -271,4 +289,28 @@
             return false;
         }
     }
+
+    private Client ignoreSslClient() {
+        SSLContext sslcontext = null;
+
+        try {
+            sslcontext = SSLContext.getInstance("TLS");
+            sslcontext.init(null, new TrustManager[]{new X509TrustManager() {
+                public void checkClientTrusted(X509Certificate[] arg0, String arg1) throws CertificateException {
+                }
+
+                public void checkServerTrusted(X509Certificate[] arg0, String arg1) throws CertificateException {
+                }
+
+                public X509Certificate[] getAcceptedIssuers() {
+                    return new X509Certificate[0];
+                }
+
+            } }, new java.security.SecureRandom());
+        } catch (NoSuchAlgorithmException | KeyManagementException e) {
+            e.printStackTrace();
+        }
+
+        return ClientBuilder.newBuilder().sslContext(sslcontext).hostnameVerifier((s1, s2) -> true).build();
+    }
 }
diff --git a/providers/rest/device/src/main/java/org/onosproject/provider/rest/device/impl/RestDeviceProvider.java b/providers/rest/device/src/main/java/org/onosproject/provider/rest/device/impl/RestDeviceProvider.java
index d8ebda6..2f25bb3 100644
--- a/providers/rest/device/src/main/java/org/onosproject/provider/rest/device/impl/RestDeviceProvider.java
+++ b/providers/rest/device/src/main/java/org/onosproject/provider/rest/device/impl/RestDeviceProvider.java
@@ -50,14 +50,7 @@
 import org.onosproject.protocol.rest.RestSBDevice;
 import org.slf4j.Logger;
 
-import javax.net.ssl.HttpsURLConnection;
-import java.io.IOException;
-import java.net.HttpURLConnection;
-import java.net.URL;
-import java.nio.charset.StandardCharsets;
-import java.security.KeyManagementException;
-import java.security.NoSuchAlgorithmException;
-import java.util.Base64;
+import javax.ws.rs.ProcessingException;
 import java.util.HashSet;
 import java.util.Set;
 import java.util.concurrent.ExecutorService;
@@ -189,9 +182,8 @@
                 UNKNOWN, UNKNOWN,
                 cid,
                 annotations);
-        providerService.deviceConnected(deviceId, deviceDescription);
         nodeId.setActive(true);
-        controller.addDevice(nodeId);
+        providerService.deviceConnected(deviceId, deviceDescription);
         addedDevices.add(deviceId);
     }
 
@@ -210,7 +202,11 @@
                 toBeRemoved.removeAll(cfg.getDevicesAddresses());
                 //Adding new devices
                 cfg.getDevicesAddresses().stream()
-                        .filter(device -> testDeviceConnection(device))
+                        .filter(device -> {
+                            device.setActive(false);
+                            controller.addDevice(device);
+                            return testDeviceConnection(device);
+                        })
                         .forEach(device -> {
                             deviceAdded(device);
                         });
@@ -237,40 +233,9 @@
 
     private boolean testDeviceConnection(RestSBDevice device) {
         try {
-            URL url;
-            if (device.url() == null) {
-                url = new URL(device.protocol(), device.ip().toString(), device.port(), "");
-            } else {
-                url = new URL(device.protocol() + URL_SEPARATOR + device.url());
-            }
-            HttpURLConnection urlConn;
-            if (device.protocol().equals(HTTPS)) {
-                //FIXME this method provides no security accepting all SSL certs.
-                RestDeviceProviderUtilities.enableSslCert();
-
-                urlConn = (HttpsURLConnection) url.openConnection();
-            } else {
-                urlConn = (HttpURLConnection) url.openConnection();
-            }
-            if (device.username() != null) {
-                String pwd = device.password() == null ? "" : ":" + device.password();
-                String userPassword = device.username() + pwd;
-                String basicAuth = Base64.getEncoder()
-                        .encodeToString(userPassword.getBytes(StandardCharsets.UTF_8));
-                urlConn.setRequestProperty(AUTHORIZATION_PROPERTY, BASIC_AUTH_PREFIX + basicAuth);
-            }
-            urlConn.setConnectTimeout(TEST_CONNECT_TIMEOUT);
-            boolean open = urlConn.getResponseCode() == (HttpsURLConnection.HTTP_OK);
-            if (!open) {
-                log.error("Device {} not accessibile, response code {} ", device,
-                          urlConn.getResponseCode());
-            }
-            urlConn.disconnect();
-            return open;
-
-        } catch (IOException | NoSuchAlgorithmException | KeyManagementException e) {
-            log.error("Device {} not reachable, error creating {} connection", device,
-                      device.protocol(), e);
+            return controller.get(device.deviceId(), "", "json") != null;
+        } catch (ProcessingException e) {
+            log.warn("Cannot connect to device {}", device, e);
         }
         return false;
     }