RC android: load bundle classes from library
[platform/upstream/iotivity.git] / service / resource-container / android / resource-container / src / main / java / org / iotivity / service / resourcecontainer / RcsResourceContainer.java
index 3eaef68..9d06a86 100644 (file)
@@ -26,6 +26,7 @@
 package org.iotivity.service.resourcecontainer;
 
 import java.util.List;
+
 import java.util.Map;
 import java.util.Enumeration;
 import android.util.Log;
@@ -35,10 +36,15 @@ import java.util.Vector;
 import dalvik.system.DexFile;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageManager;
+import dalvik.system.PathClassLoader;
+import java.net.URLClassLoader;
 
 import java.util.Hashtable;
+import java.io.File;
+import java.net.URL;
+
+import java.lang.reflect.InvocationTargetException;
 
-// TODO null check for parameters
 /**
  * This class provides APIs for managing the container and bundles in the
  * container.
@@ -46,6 +52,7 @@ import java.util.Hashtable;
 public class RcsResourceContainer implements RcsResourceContainerBundleAPI {
 
     private static final String TAG = RcsResourceContainer.class.getSimpleName();
+
     static {
         System.loadLibrary("gnustl_shared");
         System.loadLibrary("oc_logger");
@@ -59,7 +66,7 @@ public class RcsResourceContainer implements RcsResourceContainerBundleAPI {
         System.loadLibrary("rcs_container");
         System.loadLibrary("resource_container_jni");
     }
-    
+
     private Context appContext;
 
     private native void nativeStartContainer(String configFile);
@@ -114,45 +121,78 @@ public class RcsResourceContainer implements RcsResourceContainerBundleAPI {
      *            information.
      *
      */
-    public void startContainer(String configFile) {        
+    public List<RcsBundleInfo> startContainer(String configFile) {
         nativeStartContainer(configFile);
-        Log.d(TAG, "startContainer");
+        Log.d(TAG, "startContainer in Java");
         List<RcsBundleInfo> bundles = listBundles();
+        Log.d(TAG, "startContainer. There are " + bundles.size() + " bundles.");
         for(RcsBundleInfo bundleInfo : bundles){
             Log.d(TAG, "bundle-id: " + bundleInfo.getID() + ", " + bundleInfo.getPath());
-            if(bundleInfo.getPath().endsWith(".apk")){
-                String packageName = bundleInfo.getPath().replace(".apk", "");
-                try{
-                    PackageManager packageManager = appContext.getPackageManager();
-                    ApplicationInfo appInfo = packageManager.getApplicationInfo(packageName, 0);
-                    DexFile df = new DexFile(appInfo.sourceDir);
-                    ClassLoader cl = appContext.getClassLoader();
-                    for (Enumeration<String> iter = df.entries(); iter.hasMoreElements(); ) {
-                        String classN = iter.nextElement();
-                        if (classN.contains(packageName)) {
-                            Log.d(TAG,"Class: " + classN);
-                            df.loadClass(classN, cl);
-                        }
-                    }
-                    
-                    String className = bundleInfo.getActivatorName();
-                    Log.d(TAG, "Loading activator: " + className);
-                    Class activatorClass = df.loadClass(className, cl);
-                    if(activatorClass!= null){
-                        BundleActivator activator = (BundleActivator) activatorClass.
-                                getConstructor(RcsResourceContainerBundleAPI.class, Context.class).
-                                newInstance(this, appContext);
-                        activator.activateBundle();
-                        activators.put(bundleInfo.getID(), activator);
-                    }else{
-                        Log.e(TAG, "Activator is null.");
-                    }
-                }
-                catch(Exception e){
-                    Log.e(TAG, e.getMessage(), e);
+            if(bundleInfo.getPath().endsWith(".apk")){ // load classes from standalone application
+                startBundleFromStandaloneApp(bundleInfo);
+            }else if(bundleInfo.getPath().endsWith(".jar")){ // load classes from library
+                startBundleFromJar(bundleInfo);
+            }
+        }
+        return bundles;
+    }
+
+    private void startBundleFromStandaloneApp(RcsBundleInfo bundleInfo){
+        String packageName = bundleInfo.getPath().replace(".apk", "");
+        try{
+            PackageManager packageManager = appContext.getPackageManager();
+            ApplicationInfo appInfo = packageManager.getApplicationInfo(packageName, 0);
+            DexFile df = new DexFile(appInfo.sourceDir);
+            ClassLoader cl = appContext.getClassLoader();
+            for (Enumeration<String> iter = df.entries(); iter.hasMoreElements(); ) {
+                String classN = iter.nextElement();
+                if (classN.contains(packageName)) {
+                    Log.d(TAG,"Class: " + classN);
+                    df.loadClass(classN, cl);
                 }
-                Log.d(TAG, "Have to register android bundle");
             }
+            String className = bundleInfo.getActivatorName();
+            Log.d(TAG, "Loading activator: " + className);
+            Class activatorClass = df.loadClass(className, cl);
+            activateBundle(activatorClass, bundleInfo);
+        }
+        catch(Exception e){
+            Log.e(TAG, e.getMessage(), e);
+        }
+        Log.d(TAG, "Have to register android bundle");
+    }
+    
+    private void startBundleFromJar(RcsBundleInfo bundleInfo){
+        try{
+            Log.e(TAG, "Loading from .jar file.");
+            
+            PathClassLoader classLoader = new PathClassLoader(bundleInfo.getPath(),
+                    RcsResourceContainer.class.getClassLoader());
+           
+            String className = bundleInfo.getActivatorName().replace('/', '.');
+            Log.d(TAG, "Loading activator: " + className);
+            Class activatorClass = Class.forName(className, true, classLoader);
+
+            activateBundle(activatorClass, bundleInfo);
+        }
+        catch(Exception e){
+            Log.e(TAG, e.getMessage(), e);
+        }
+        Log.d(TAG, "Have to register android bundle");
+    }
+    
+    private void activateBundle(Class activatorClass, RcsBundleInfo bundleInfo) throws
+        NoSuchMethodException, InstantiationException, IllegalAccessException, 
+        InvocationTargetException{
+        if(activatorClass!= null){
+            BundleActivator activator = (BundleActivator) activatorClass.
+                    getConstructor(RcsResourceContainerBundleAPI.class, Context.class).
+                    newInstance(this, appContext);
+            activator.activateBundle();
+            activators.put(bundleInfo.getID(), activator);
+            bundleInfo.setActivated(true);
+        }else{
+            Log.e(TAG, "Activator is null.");
         }
     }
 
@@ -227,49 +267,21 @@ public class RcsResourceContainer implements RcsResourceContainerBundleAPI {
     public void startBundle(String bundleId) {
         Log.d(TAG, "startBundle");
         List<RcsBundleInfo> bundles = listBundles();
-       
-        for(RcsBundleInfo bundleInfo : bundles){          
+
+        for(RcsBundleInfo bundleInfo : bundles){
             if(bundleInfo.getID().equals(bundleId) && bundleInfo.getLibraryPath().endsWith(".apk")){
                 Log.d(TAG, "Have to start android bundle");
                 Log.d(TAG, "bundle-id: " + bundleInfo.getID() + ", " + bundleInfo.getPath());
                 if(bundleInfo.getPath().endsWith(".apk")){
-                    String packageName = bundleInfo.getPath().replace(".apk", "");
-                    try{
-                        PackageManager packageManager = appContext.getPackageManager();
-                        ApplicationInfo appInfo = packageManager.getApplicationInfo(packageName, 0);
-                        DexFile df = new DexFile(appInfo.sourceDir);
-                        ClassLoader cl = appContext.getClassLoader();
-                        for (Enumeration<String> iter = df.entries(); iter.hasMoreElements(); ) {
-                            String classN = iter.nextElement();
-                            if (classN.contains(packageName)) {
-                                Log.d(TAG,"Class: " + classN);
-                                df.loadClass(classN, cl);
-                            }
-                        }
-                        
-                        String className = bundleInfo.getActivatorName();
-                        Log.d(TAG, "Loading activator: " + className);
-                        Class activatorClass = df.loadClass(className, cl);
-                        if(activatorClass!= null){
-                            BundleActivator activator = (BundleActivator) activatorClass.
-                                    getConstructor(RcsResourceContainerBundleAPI.class, 
-                                            Context.class).
-                                    newInstance(this, appContext);
-                            activator.activateBundle();
-                        }else{
-                            Log.e(TAG, "Activator is null.");
-                        }
-                    }
-                    catch(Exception e){
-                        Log.e(TAG, e.getMessage(), e);
-                    }
-                    Log.d(TAG, "Have to register android bundle");
+                    startBundleFromStandaloneApp(bundleInfo);
+                }else if(bundleInfo.getID().equals(bundleId) &&
+                        bundleInfo.getPath().endsWith(".jar")){ // load classes from library
+                    startBundleFromJar(bundleInfo);
                 }
             }else{
                 nativeStartBundle(bundleId);
             }
         }
-      
     }
 
     /**
@@ -324,6 +336,14 @@ public class RcsResourceContainer implements RcsResourceContainerBundleAPI {
         return nativeListBundleResources(bundleId);
     }
 
+    /**
+     * Registers a bundle resource
+     *
+     * @param bundleId
+     *            Id of the Bundle
+     * @param resource
+     *            resource to be registered
+     */
     public void registerResource(String bundleId, BundleResource resource){
         Log.d(TAG, "register Resource");
         // bundleResources.add(resource);
@@ -331,7 +351,15 @@ public class RcsResourceContainer implements RcsResourceContainerBundleAPI {
                         resource.getURI(), resource.getResourceType(),
                         resource.getName());
     }
-    
+
+    /**
+     * Returns the bundle configuration for the resources
+     *
+     * @param bundleId
+     *            Id of the Bundle
+     *
+     * @return List<ResourceConfig> All the resource configurations for the given bundle
+     */
     public List<ResourceConfig> getConfiguredBundleResources(String bundleId) {
         Log.d(TAG, "getConfiguredBundleResource " + bundleId);
         int configuredResources = getNumberOfConfiguredResources(bundleId);
@@ -343,22 +371,42 @@ public class RcsResourceContainer implements RcsResourceContainerBundleAPI {
                 String[] resourceParams = getConfiguredResourceParams(bundleId, i);
                 ResourceConfig config = new ResourceConfig(resourceParams);
                 configs.add(config);
-
         }
         return configs;
     }
 
-    
+    /**
+     * Unregisters a bundle resource
+     *
+     * @param resource
+     *            Resource to be unregistered
+     */
     public void unregisterResource(BundleResource resource){
         Log.d(TAG, "unregister Resource");
         nativeUnregisterBundleResource(resource, resource.getURI());
     }
 
+    /**
+     * Returns the number of configured resources
+     *
+     * @param bundleId
+     *            Id of the Bundle
+     * @return number of configured resources
+     */
     public int getNumberOfConfiguredResources(String bundleId){
         Log.d(TAG, "getNumberOfConfiguredResources");
         return nativeGetNumberOfConfiguredResources(bundleId);
     }
 
+    /**
+     * Provides the configured resource parameter
+     *
+     * @param bundleId
+     *            Id of the Bundle
+     * @param resId
+                  Continuous numeric identifier within the bundle
+     * @return resource paramaters such as URI, resource type, name, etc. for the resource
+     */
     public String[] getConfiguredResourceParams(String bundleId, int resId){
         Log.d(TAG, "getConfiguredResourceParams");
         return nativeGetConfiguredResourceParams(bundleId, resId);