ONOS-542 Defining application subsystem interfaces & public constructs.

Change-Id: Iba0d2cb69dace5beee8a68def9918059ce755b5c
diff --git a/web/api/src/main/java/org/onosproject/codec/impl/ApplicationCodec.java b/web/api/src/main/java/org/onosproject/codec/impl/ApplicationCodec.java
new file mode 100644
index 0000000..4cf0b7c
--- /dev/null
+++ b/web/api/src/main/java/org/onosproject/codec/impl/ApplicationCodec.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * 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.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.codec.impl;
+
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import org.onosproject.app.ApplicationService;
+import org.onosproject.codec.CodecContext;
+import org.onosproject.codec.JsonCodec;
+import org.onosproject.core.Application;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+/**
+ * Application JSON codec.
+ */
+public class ApplicationCodec extends JsonCodec<Application> {
+
+    @Override
+    public ObjectNode encode(Application app, CodecContext context) {
+        checkNotNull(app, "Application cannot be null");
+        ApplicationService service = context.get(ApplicationService.class);
+        ObjectNode result = context.mapper().createObjectNode()
+                .put("name", app.id().name())
+                .put("id", app.id().id())
+                .put("version", app.version().toString())
+                .put("description", app.description())
+                .put("origin", app.origin())
+                .put("permissions", app.permissions().toString())
+                .put("featuresRepo", app.featuresRepo().isPresent() ?
+                        app.featuresRepo().toString() : "")
+                .put("features", app.features().toString())
+                .put("state", service.getState(app.id()).toString());
+        return result;
+    }
+
+}
diff --git a/web/api/src/main/java/org/onosproject/codec/impl/CodecManager.java b/web/api/src/main/java/org/onosproject/codec/impl/CodecManager.java
index d176077..88fb8dd 100644
--- a/web/api/src/main/java/org/onosproject/codec/impl/CodecManager.java
+++ b/web/api/src/main/java/org/onosproject/codec/impl/CodecManager.java
@@ -26,6 +26,7 @@
 import org.onlab.packet.Ethernet;
 import org.onosproject.codec.CodecService;
 import org.onosproject.codec.JsonCodec;
+import org.onosproject.core.Application;
 import org.onosproject.net.Annotations;
 import org.onosproject.net.ConnectPoint;
 import org.onosproject.net.Device;
@@ -64,6 +65,7 @@
     @Activate
     public void activate() {
         codecs.clear();
+        registerCodec(Application.class, new ApplicationCodec());
         registerCodec(Annotations.class, new AnnotationsCodec());
         registerCodec(Device.class, new DeviceCodec());
         registerCodec(Port.class, new PortCodec());
diff --git a/web/api/src/main/java/org/onosproject/rest/ApplicationsWebResource.java b/web/api/src/main/java/org/onosproject/rest/ApplicationsWebResource.java
new file mode 100644
index 0000000..6177bab
--- /dev/null
+++ b/web/api/src/main/java/org/onosproject/rest/ApplicationsWebResource.java
@@ -0,0 +1,99 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * 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.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.rest;
+
+import org.onosproject.app.ApplicationAdminService;
+import org.onosproject.core.Application;
+import org.onosproject.core.ApplicationId;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.DELETE;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import java.io.InputStream;
+import java.util.Set;
+
+/**
+ * REST resource for interacting with the inventory of applications.
+ */
+@Path("applications")
+public class ApplicationsWebResource extends AbstractWebResource {
+
+    @GET
+    public Response getApplications() {
+        ApplicationAdminService service = get(ApplicationAdminService.class);
+        Set<Application> apps = service.getApplications();
+        return ok(encodeArray(Application.class, "applications", apps)).build();
+    }
+
+    @GET
+    @Path("{name}")
+    public Response getApplication(@PathParam("id") String name) {
+        ApplicationAdminService service = get(ApplicationAdminService.class);
+        ApplicationId appId = service.getId(name);
+        return response(service, appId);
+    }
+
+    @POST
+    @Consumes(MediaType.APPLICATION_OCTET_STREAM)
+    @Produces(MediaType.APPLICATION_JSON)
+    public Response installApplication(InputStream stream) {
+        ApplicationAdminService service = get(ApplicationAdminService.class);
+        Application app = service.install(stream);
+        return ok(codec(Application.class).encode(app, this)).build();
+    }
+
+    @DELETE
+    @Produces(MediaType.APPLICATION_JSON)
+    @Path("{name}")
+    public Response uninstallApplication(@PathParam("name") String name) {
+        ApplicationAdminService service = get(ApplicationAdminService.class);
+        ApplicationId appId = service.getId(name);
+        service.uninstall(appId);
+        return Response.ok().build();
+    }
+
+    @POST
+    @Produces(MediaType.APPLICATION_JSON)
+    @Path("{name}/active")
+    public Response activateApplication(@PathParam("name") String name) {
+        ApplicationAdminService service = get(ApplicationAdminService.class);
+        ApplicationId appId = service.getId(name);
+        service.activate(appId);
+        return response(service, appId);
+    }
+
+    @DELETE
+    @Produces(MediaType.APPLICATION_JSON)
+    @Path("{name}/active")
+    public Response deactivateApplication(@PathParam("name") String name) {
+        ApplicationAdminService service = get(ApplicationAdminService.class);
+        ApplicationId appId = service.getId(name);
+        service.deactivate(appId);
+        return response(service, appId);
+    }
+
+    private Response response(ApplicationAdminService service, ApplicationId appId) {
+        Application app = service.getApplication(appId);
+        return ok(codec(Application.class).encode(app, this)).build();
+    }
+
+}
diff --git a/web/api/src/main/webapp/WEB-INF/web.xml b/web/api/src/main/webapp/WEB-INF/web.xml
index d8fb9e7..e0e4737 100644
--- a/web/api/src/main/webapp/WEB-INF/web.xml
+++ b/web/api/src/main/webapp/WEB-INF/web.xml
@@ -35,6 +35,7 @@
                 org.onosproject.rest.exceptions.ServerErrorMapper,
                 org.onosproject.rest.JsonBodyWriter,
 
+                org.onosproject.rest.ApplicationsWebResource,
                 org.onosproject.rest.DevicesWebResource,
                 org.onosproject.rest.LinksWebResource,
                 org.onosproject.rest.HostsWebResource,
diff --git a/web/api/src/test/java/org/onosproject/codec/impl/IntentCodecTest.java b/web/api/src/test/java/org/onosproject/codec/impl/IntentCodecTest.java
index a230273..d96f481 100644
--- a/web/api/src/test/java/org/onosproject/codec/impl/IntentCodecTest.java
+++ b/web/api/src/test/java/org/onosproject/codec/impl/IntentCodecTest.java
@@ -66,8 +66,7 @@
 
     private final HostId id1 = hid("12:34:56:78:91:ab/1");
     private final HostId id2 = hid("12:34:56:78:92:ab/1");
-    private final ApplicationId appId =
-            new DefaultApplicationId((short) 3, "test");
+    private final ApplicationId appId = new DefaultApplicationId(3, "test");
     final TrafficSelector emptySelector =
             DefaultTrafficSelector.builder().build();
     final TrafficTreatment emptyTreatment =
diff --git a/web/api/src/test/java/org/onosproject/rest/IntentsResourceTest.java b/web/api/src/test/java/org/onosproject/rest/IntentsResourceTest.java
index 2d650a5..b2eee81 100644
--- a/web/api/src/test/java/org/onosproject/rest/IntentsResourceTest.java
+++ b/web/api/src/test/java/org/onosproject/rest/IntentsResourceTest.java
@@ -62,8 +62,7 @@
 public class IntentsResourceTest extends ResourceTest {
     final IntentService mockIntentService = createMock(IntentService.class);
     final HashSet<Intent> intents = new HashSet<>();
-    private static final ApplicationId APP_ID =
-            new DefaultApplicationId((short) 1, "test");
+    private static final ApplicationId APP_ID = new DefaultApplicationId(1, "test");
     private IdGenerator mockGenerator;
 
     /**