added OAuth2 authentication for REST protocol

Change-Id: I3b8f3943ea043587730870a0b861760a4d6f3aa7
diff --git a/protocols/rest/api/BUCK b/protocols/rest/api/BUCK
index 74f33b2..471084f 100644
--- a/protocols/rest/api/BUCK
+++ b/protocols/rest/api/BUCK
@@ -3,6 +3,7 @@
     '//utils/rest:onlab-rest',
     '//lib:CORE_DEPS',
     '//lib:jersey-client',
+    '//lib:jersey-security',
     '//lib:jersey-common',
     '//lib:httpclient-osgi',
     '//lib:httpcore-osgi',
diff --git a/protocols/rest/api/pom.xml b/protocols/rest/api/pom.xml
index ff5f7de..e334e7a 100644
--- a/protocols/rest/api/pom.xml
+++ b/protocols/rest/api/pom.xml
@@ -35,6 +35,12 @@
             <groupId>org.glassfish.jersey.core</groupId>
             <artifactId>jersey-client</artifactId>
         </dependency>
+
+        <dependency>
+            <groupId>org.glassfish.jersey.security</groupId>
+            <artifactId>oauth2-client</artifactId>
+        </dependency>
+
         <dependency>
             <groupId>org.apache.httpcomponents</groupId>
             <artifactId>httpclient-osgi</artifactId>
@@ -43,7 +49,6 @@
         <dependency>
             <groupId>commons-io</groupId>
             <artifactId>commons-io</artifactId>
-            <version>2.4</version>
         </dependency>
         <dependency>
           <groupId>junit</groupId>
diff --git a/protocols/rest/api/src/main/java/org/onosproject/protocol/http/ctl/HttpSBControllerImpl.java b/protocols/rest/api/src/main/java/org/onosproject/protocol/http/ctl/HttpSBControllerImpl.java
index 4a893fcb..602d989 100644
--- a/protocols/rest/api/src/main/java/org/onosproject/protocol/http/ctl/HttpSBControllerImpl.java
+++ b/protocols/rest/api/src/main/java/org/onosproject/protocol/http/ctl/HttpSBControllerImpl.java
@@ -25,10 +25,12 @@
 import org.apache.http.impl.client.HttpClients;
 import org.apache.http.ssl.SSLContextBuilder;
 import org.glassfish.jersey.client.authentication.HttpAuthenticationFeature;
+import org.glassfish.jersey.client.oauth2.OAuth2ClientSupport;
 import org.onlab.packet.IpAddress;
 import org.onosproject.net.DeviceId;
 import org.onosproject.protocol.http.HttpSBController;
 import org.onosproject.protocol.rest.RestSBDevice;
+import org.onosproject.protocol.rest.RestSBDevice.AuthenticationScheme;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -55,6 +57,8 @@
 import java.util.Map;
 import java.util.concurrent.ConcurrentHashMap;
 
+import static com.google.common.base.Preconditions.checkNotNull;
+
 /**
  * The implementation of HttpSBController.
  */
@@ -102,11 +106,7 @@
     public void addDevice(RestSBDevice 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);
-            }
+            authenticate(client, device);
             clientMap.put(device.deviceId(), client);
             deviceMap.put(device.deviceId(), device);
         } else {
@@ -283,8 +283,23 @@
         }
     }
 
-    private void authenticate(Client client, String username, String password) {
-        client.register(HttpAuthenticationFeature.basic(username, password));
+    private void authenticate(Client client, RestSBDevice device) {
+        AuthenticationScheme authScheme = device.authentication();
+        if (authScheme == AuthenticationScheme.NO_AUTHENTICATION) {
+            log.debug("{} scheme is specified, ignoring authentication", authScheme);
+            return;
+        } else if (authScheme == AuthenticationScheme.OAUTH2) {
+            String token = checkNotNull(device.token());
+            client.register(OAuth2ClientSupport.feature(token));
+        } else if (authScheme == AuthenticationScheme.BASIC) {
+            String username = device.username();
+            String password = device.password() == null ? "" : device.password();
+            client.register(HttpAuthenticationFeature.basic(username, password));
+        } else {
+            // TODO: Add support for other authentication schemes here.
+            throw new IllegalArgumentException(String.format("Unsupported authentication scheme: %s",
+                    authScheme.name()));
+        }
     }
 
     protected WebTarget getWebTarget(DeviceId device, String request) {
@@ -343,12 +358,15 @@
         try {
             sslcontext = SSLContext.getInstance("TLS");
             sslcontext.init(null, new TrustManager[]{new X509TrustManager() {
+                @Override
                 public void checkClientTrusted(X509Certificate[] arg0, String arg1) throws CertificateException {
                 }
 
+                @Override
                 public void checkServerTrusted(X509Certificate[] arg0, String arg1) throws CertificateException {
                 }
 
+                @Override
                 public X509Certificate[] getAcceptedIssuers() {
                     return new X509Certificate[0];
                 }
diff --git a/protocols/rest/api/src/main/java/org/onosproject/protocol/rest/DefaultRestSBDevice.java b/protocols/rest/api/src/main/java/org/onosproject/protocol/rest/DefaultRestSBDevice.java
index 8f59093..fef7f37 100644
--- a/protocols/rest/api/src/main/java/org/onosproject/protocol/rest/DefaultRestSBDevice.java
+++ b/protocols/rest/api/src/main/java/org/onosproject/protocol/rest/DefaultRestSBDevice.java
@@ -41,6 +41,8 @@
     private String protocol;
     private String url;
     private boolean isProxy;
+    private AuthenticationScheme authenticationScheme;
+    private String token;
     private final Optional<String> testUrl;
     private final Optional<String> manufacturer;
     private final Optional<String> hwVersion;
@@ -48,13 +50,13 @@
 
     public DefaultRestSBDevice(IpAddress ip, int port, String name, String password,
                                String protocol, String url, boolean isActive) {
-        this(ip, port, name, password, protocol, url, isActive, "", "", "", "");
+        this(ip, port, name, password, protocol, url, isActive, "", "", "", "", AuthenticationScheme.BASIC, "");
     }
 
     public DefaultRestSBDevice(IpAddress ip, int port, String name, String password,
                                String protocol, String url, boolean isActive, String testUrl, String manufacturer,
-                               String hwVersion,
-                               String swVersion) {
+                               String hwVersion, String swVersion, AuthenticationScheme authenticationScheme,
+                               String token) {
         Preconditions.checkNotNull(ip, "IP address cannot be null");
         Preconditions.checkArgument(port > 0, "Port address cannot be negative");
         Preconditions.checkNotNull(protocol, "protocol address cannot be null");
@@ -65,6 +67,8 @@
         this.isActive = isActive;
         this.protocol = protocol;
         this.url = StringUtils.isEmpty(url) ? null : url;
+        this.authenticationScheme = authenticationScheme;
+        this.token = token;
         this.manufacturer = StringUtils.isEmpty(manufacturer) ?
                 Optional.empty() : Optional.ofNullable(manufacturer);
         this.hwVersion = StringUtils.isEmpty(hwVersion) ?
@@ -159,6 +163,16 @@
     }
 
     @Override
+    public AuthenticationScheme authentication() {
+        return authenticationScheme;
+    }
+
+    @Override
+    public String token() {
+        return token;
+    }
+
+    @Override
     public String toString() {
         return MoreObjects.toStringHelper(this)
                 .omitNullValues()
@@ -168,6 +182,8 @@
                 .add("username", username)
                 .add("port", port)
                 .add("ip", ip)
+                .add("authentication", authenticationScheme.name())
+                .add("token", token)
                 .add("manufacturer", manufacturer.orElse(null))
                 .add("hwVersion", hwVersion.orElse(null))
                 .add("swVersion", swVersion.orElse(null))
diff --git a/protocols/rest/api/src/main/java/org/onosproject/protocol/rest/RestSBDevice.java b/protocols/rest/api/src/main/java/org/onosproject/protocol/rest/RestSBDevice.java
index edcce6e..6767b2d 100644
--- a/protocols/rest/api/src/main/java/org/onosproject/protocol/rest/RestSBDevice.java
+++ b/protocols/rest/api/src/main/java/org/onosproject/protocol/rest/RestSBDevice.java
@@ -26,6 +26,16 @@
  */
 public interface RestSBDevice {
     /**
+     * REST Authentication schemes.
+     */
+    public enum AuthenticationScheme {
+        NO_AUTHENTICATION,
+        BASIC,
+        OAUTH,
+        OAUTH2,
+    }
+
+    /**
      * Returns the ip of this device.
      *
      * @return ip
@@ -40,6 +50,20 @@
     int port();
 
     /**
+     * The authentication scheme of rest device.
+     *
+     * @return authentication
+     */
+    AuthenticationScheme authentication();
+
+    /**
+     * The access token of rest device if authentication is OAuth2.
+     *
+     * @return token
+     */
+    String token();
+
+    /**
      * Returns the username of this device.
      *
      * @return username
@@ -91,6 +115,7 @@
     /**
      * Returns the proxy state of this device
      * (if true, the device is proxying multiple ONOS devices).
+     *
      * @return proxy state
      */
     boolean isProxy();
@@ -122,4 +147,5 @@
      * @return the software version.
      */
     Optional<String> swVersion();
+
 }