allow applications to be installed by URL from REST API

Change-Id: I6c28d91e1bbc6e77eefba00b8f106fe22edc475b
diff --git a/tools/dev/bin/onos-app b/tools/dev/bin/onos-app
index d6fe562..fb6fff6 100755
--- a/tools/dev/bin/onos-app
+++ b/tools/dev/bin/onos-app
@@ -9,6 +9,7 @@
 
 export URL=http://$node:8181/onos/v1/applications
 export HDR="-HContent-Type:application/octet-stream"
+export HAJ="-HContent-Type:application/json"
 export curl="curl -sS --user $ONOS_WEB_USER:$ONOS_WEB_PASS"
 
 # Prints usage help
@@ -34,6 +35,13 @@
 
 case $cmd in
     list) $curl -X GET $URL;;
+    installUrl!|installUrl)
+        activate="false"
+        [ $cmd = "installUrl!" ] && activate="true"
+        [ $# -lt 3 ] && usage
+        appurl=$3
+        $curl -X POST $HAJ -d '{"url" : "'"$appurl"'", "activate" : "'$activate'" }' $URL
+        ;;
     install!|install)
         [ $cmd = "install!" ] && activate="?activate=true"
         [ $# -lt 3 -o ! -f $app ] && usage
diff --git a/web/api/src/main/java/org/onosproject/rest/resources/ApplicationsWebResource.java b/web/api/src/main/java/org/onosproject/rest/resources/ApplicationsWebResource.java
index 6ee5c83..f02947a 100644
--- a/web/api/src/main/java/org/onosproject/rest/resources/ApplicationsWebResource.java
+++ b/web/api/src/main/java/org/onosproject/rest/resources/ApplicationsWebResource.java
@@ -15,6 +15,7 @@
  */
 package org.onosproject.rest.resources;
 
+import com.fasterxml.jackson.databind.node.ObjectNode;
 import org.onosproject.app.ApplicationAdminService;
 import org.onosproject.core.Application;
 import org.onosproject.core.ApplicationId;
@@ -32,7 +33,9 @@
 import javax.ws.rs.QueryParam;
 import javax.ws.rs.core.MediaType;
 import javax.ws.rs.core.Response;
+import java.io.IOException;
 import java.io.InputStream;
+import java.net.URL;
 import java.util.Set;
 
 import static org.onlab.util.Tools.nullIsNotFound;
@@ -46,6 +49,9 @@
     private static final String APP_ID_NOT_FOUND = "Application ID is not found";
     private static final String APP_NOT_FOUND = "Application is not found";
 
+    private static final String URL = "url";
+    private static final String ACTIVATE = "activate";
+
     /**
      * Get all installed applications.
      * Returns array of all installed applications.
@@ -80,6 +86,38 @@
      * Install a new application.
      * Uploads application archive stream and optionally activates the
      * application.
+
+     * @param raw   json object containing location (url) of application oar
+     * @return 200 OK; 404; 401
+     */
+    @POST
+    @Consumes(MediaType.APPLICATION_JSON)
+    @Produces(MediaType.APPLICATION_JSON)
+    public Response installApp(InputStream raw) {
+        Application app;
+        try {
+            ObjectNode jsonTree = (ObjectNode) mapper().readTree(raw);
+            URL url = new URL(jsonTree.get(URL).asText());
+            boolean activate = false;
+            if (jsonTree.has(ACTIVATE)) {
+              activate = jsonTree.get(ACTIVATE).asBoolean();
+            }
+
+            ApplicationAdminService service = get(ApplicationAdminService.class);
+            app = service.install(url.openStream());
+            if (activate) {
+                service.activate(app.id());
+            }
+        } catch (IOException ex) {
+            throw new IllegalArgumentException(ex);
+        }
+        return ok(codec(Application.class).encode(app, this)).build();
+    }
+
+    /**
+     * Install a new application.
+     * Uploads application archive stream and optionally activates the
+     * application.
      *
      * @param activate true to activate app also
      * @param stream   application archive stream