[ONOS-3634] Enhance app to have a category, icon, URL and readme

This commmit enhances application to have category, icon, URL and
readme. The web GUI and CLI will be implemented in separate commits

Change-Id: Ib02716d7118cc617b24f196f2213ea1fe99a34be
diff --git a/core/common/src/main/java/org/onosproject/common/app/ApplicationArchive.java b/core/common/src/main/java/org/onosproject/common/app/ApplicationArchive.java
index ab03ab2..42f8c9c 100644
--- a/core/common/src/main/java/org/onosproject/common/app/ApplicationArchive.java
+++ b/core/common/src/main/java/org/onosproject/common/app/ApplicationArchive.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2015 Open Networking Laboratory
+ * Copyright 2015-2016 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.
@@ -23,6 +23,7 @@
 import org.apache.commons.configuration.ConfigurationException;
 import org.apache.commons.configuration.HierarchicalConfiguration;
 import org.apache.commons.configuration.XMLConfiguration;
+import org.apache.commons.lang.StringUtils;
 import org.onlab.util.Tools;
 import org.onosproject.app.ApplicationDescription;
 import org.onosproject.app.ApplicationEvent;
@@ -37,6 +38,10 @@
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import javax.imageio.ImageIO;
+import java.awt.image.BufferedImage;
+import java.awt.image.DataBufferByte;
+import java.awt.image.WritableRaster;
 import java.io.ByteArrayInputStream;
 import java.io.File;
 import java.io.FileInputStream;
@@ -81,6 +86,10 @@
     private static final String APPS = "[@apps]";
     private static final String DESCRIPTION = "description";
 
+    private static final String CATEGORY = "[@category]";
+    private static final String URL = "[@url]";
+    private static final String README = "readme";
+
     private static final String ROLE = "security.role";
     private static final String APP_PERMISSIONS = "security.permissions.app-perm";
     private static final String NET_PERMISSIONS = "security.permissions.net-perm";
@@ -88,6 +97,7 @@
 
     private static final String OAR = ".oar";
     private static final String APP_XML = "app.xml";
+    private static final String ICON_PNG = "icon.png";
     private static final String M2_PREFIX = "m2";
 
     private static final String ROOT = "../";
@@ -283,8 +293,10 @@
     private ApplicationDescription loadAppDescription(XMLConfiguration cfg) {
         String name = cfg.getString(NAME);
         Version version = Version.version(cfg.getString(VERSION));
-        String desc = cfg.getString(DESCRIPTION);
         String origin = cfg.getString(ORIGIN);
+        String category = cfg.getString(CATEGORY);
+        String url = cfg.getString(URL);
+        byte[] icon = getApplicationIcon(name);
         ApplicationRole role = getRole(cfg.getString(ROLE));
         Set<Permission> perms = getPermissions(cfg);
         String featRepo = cfg.getString(FEATURES_REPO);
@@ -295,7 +307,17 @@
         List<String> requiredApps = apps.isEmpty() ?
                 ImmutableList.of() : ImmutableList.copyOf(apps.split(","));
 
-        return new DefaultApplicationDescription(name, version, desc, origin, role,
+        String desc = cfg.getString(DESCRIPTION);
+        String readme = cfg.getString(README);
+
+        if (readme == null) {
+            readme = desc;
+        } else {
+            desc = compactDescription(readme);
+        }
+
+        return new DefaultApplicationDescription(name, version, desc, origin,
+                category, url, readme, icon, role,
                                                  perms, featuresRepo, features,
                                                  requiredApps);
     }
@@ -387,7 +409,6 @@
         return appFile(appName, "active").exists();
     }
 
-
     // Returns the name of the file located under the specified app directory.
     private File appFile(String appName, String fileName) {
         return new File(new File(appsDir, appName), fileName);
@@ -420,7 +441,33 @@
         return ImmutableSet.copyOf(permissionList);
     }
 
-    //
+    // Returns the byte stream from icon.png file in oar application archive.
+    private byte[] getApplicationIcon(String appName) {
+        // open image
+        File iconFile = appFile(appName, ICON_PNG);
+
+        if (!iconFile.exists()) {
+            iconFile = new File(appsDir, ICON_PNG);
+        }
+
+        if (!iconFile.exists()) {
+            return null;
+        }
+
+        BufferedImage bufferedImage = null;
+        try {
+            bufferedImage = ImageIO.read(iconFile);
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+
+        // get DataBufferBytes from Raster
+        WritableRaster raster = bufferedImage .getRaster();
+        DataBufferByte data = (DataBufferByte) raster.getDataBuffer();
+
+        return data.getData();
+    }
+
     // Returns application role type
     public ApplicationRole getRole(String value) {
         if (value == null) {
@@ -434,4 +481,16 @@
             }
         }
     }
+
+    // Returns the first sentence of the given sentence
+    private String compactDescription(String sentence) {
+        if (StringUtils.isNotEmpty(sentence)) {
+            if (StringUtils.contains(sentence, ".")) {
+                return StringUtils.substringBefore(sentence, ".") + ".";
+            } else {
+                return sentence + ".";
+            }
+        }
+        return sentence;
+    }
 }