Merge branch 'upstream' into tizen
[platform/upstream/iotivity.git] / service / resource-container / android / resource-container / src / main / java / org / iotivity / service / resourcecontainer / RcsResourceContainer.java
1 //******************************************************************
2 //
3 // Copyright 2015 Samsung Electronics All Rights Reserved.
4 //
5 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
6 //
7 // Licensed under the Apache License, Version 2.0 (the "License");
8 // you may not use this file except in compliance with the License.
9 // You may obtain a copy of the License at
10 //
11 //      http://www.apache.org/licenses/LICENSE-2.0
12 //
13 // Unless required by applicable law or agreed to in writing, software
14 // distributed under the License is distributed on an "AS IS" BASIS,
15 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 // See the License for the specific language governing permissions and
17 // limitations under the License.
18 //
19 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
20
21
22 /**
23  * @file
24  * This file contains the Resource Container APIs
25  */
26 package org.iotivity.service.resourcecontainer;
27
28 import java.util.List;
29
30 import java.util.Map;
31 import java.util.Enumeration;
32 import android.util.Log;
33 import android.content.Context;
34 import java.util.Vector;
35
36 import dalvik.system.DexFile;
37 import android.content.pm.ApplicationInfo;
38 import android.content.pm.PackageManager;
39 import dalvik.system.PathClassLoader;
40 import java.net.URLClassLoader;
41
42 import java.util.Hashtable;
43 import java.io.File;
44 import java.net.URL;
45
46 import java.lang.reflect.InvocationTargetException;
47
48 /**
49  * This class provides APIs for managing the container and bundles in the
50  * container.
51  */
52 public class RcsResourceContainer implements RcsResourceContainerBundleAPI {
53
54     private static final String TAG = RcsResourceContainer.class.getSimpleName();
55
56     static {
57         System.loadLibrary("gnustl_shared");
58         System.loadLibrary("oc_logger");
59         System.loadLibrary("connectivity_abstraction");
60         System.loadLibrary("ca-interface");
61         System.loadLibrary("octbstack");
62         System.loadLibrary("oc");
63         System.loadLibrary("rcs_client");
64         System.loadLibrary("rcs_server");
65         System.loadLibrary("rcs_common");
66         System.loadLibrary("rcs_container");
67         System.loadLibrary("resource_container_jni");
68     }
69
70     private Context appContext;
71
72     private native void nativeStartContainer(String configFile);
73
74     private native void nativeStopContainer();
75
76     private native void nativeAddBundle(String bundleId, String bundleUri,
77             String bundlePath, String activator, Map<String, String> params);
78
79     private native void nativeRemoveBundle(String bundleId);
80
81     private native List<RcsBundleInfo> nativeListBundles();
82
83     private native void nativeStartBundle(String bundleId);
84
85     private native void nativeStopBundle(String bundleId);
86
87     private native void nativeAddResourceConfig(String bundleId,
88             String resourceUri, Map<String, String> params);
89
90     private native void nativeRemoveResourceConfig(String bundleId,
91             String resourceUri);
92
93     private native List<String> nativeListBundleResources(String bundleId);
94     
95     private native void nativeRegisterBundleResource(BundleResource resource,
96         String[] attributes, String bundleId, String uri,
97         String resourceType, String name);
98     
99     private native void nativeUnregisterBundleResource(BundleResource resource,
100         String uri);
101     
102     private native int nativeGetNumberOfConfiguredResources(String bundleId);
103         
104     private native String[] nativeGetConfiguredResourceParams(String bundleId,
105         int resId);  
106     
107     public RcsResourceContainer(Context appContext){
108         this.appContext = appContext;
109     }
110     
111     private Hashtable<String, BundleActivator> activators = new Hashtable<String, BundleActivator>();
112
113     /**
114      * API for starting the Container
115      *
116      * <p>
117      * This API start the container with the provided Configuration file.
118      *
119      * @param configFile
120      *            configuration File that contains the Bundle/Bundles
121      *            information.
122      *
123      */
124     public List<RcsBundleInfo> startContainer(String configFile) {
125         if(configFile == null || configFile.isEmpty()){
126             throw new IllegalArgumentException(
127                 "Configuration file is null or empty.");
128         }
129         nativeStartContainer(configFile);
130         Log.d(TAG, "startContainer in Java");
131         List<RcsBundleInfo> bundles = listBundles();
132         Log.d(TAG, "startContainer. There are " + bundles.size() + " bundles.");
133         for(RcsBundleInfo bundleInfo : bundles){
134             Log.d(TAG, "bundle-id: " + bundleInfo.getID() + ", " + bundleInfo.getPath());
135             if(bundleInfo.getPath().endsWith(".apk")){ // load classes from standalone application
136                 startBundleFromStandaloneApp(bundleInfo);
137             }else if(bundleInfo.getPath().endsWith(".jar")){ // load classes from library
138                 startBundleFromJar(bundleInfo);
139             }
140         }
141         return bundles;
142     }
143
144     private void startBundleFromStandaloneApp(RcsBundleInfo bundleInfo){
145         if(bundleInfo == null){
146             throw new IllegalArgumentException(
147                 "bundleInfo parameter is null or empty.");
148         }
149         String packageName = bundleInfo.getPath().replace(".apk", "");
150         try{
151             PackageManager packageManager = appContext.getPackageManager();
152             ApplicationInfo appInfo = packageManager.getApplicationInfo(packageName, 0);
153             DexFile df = new DexFile(appInfo.sourceDir);
154             ClassLoader cl = appContext.getClassLoader();
155             for (Enumeration<String> iter = df.entries(); iter.hasMoreElements(); ) {
156                 String classN = iter.nextElement();
157                 if (classN.contains(packageName)) {
158                     Log.d(TAG,"Class: " + classN);
159                     df.loadClass(classN, cl);
160                 }
161             }
162             String className = bundleInfo.getActivatorName();
163             Log.d(TAG, "Loading activator: " + className);
164             Class activatorClass = df.loadClass(className, cl);
165             activateBundle(activatorClass, bundleInfo);
166         }
167         catch(Exception e){
168             Log.e(TAG, e.getMessage(), e);
169         }
170         Log.d(TAG, "Have to register android bundle");
171     }
172     
173     private void startBundleFromJar(RcsBundleInfo bundleInfo){
174         if(bundleInfo == null){
175             throw new IllegalArgumentException(
176                 "bundleInfo parameter is null");
177         }
178         try{
179             Log.e(TAG, "Loading from .jar file.");
180             
181             PathClassLoader classLoader = new PathClassLoader(bundleInfo.getPath(),
182                     RcsResourceContainer.class.getClassLoader());
183            
184             String className = bundleInfo.getActivatorName().replace('/', '.');
185             Log.d(TAG, "Loading activator: " + className);
186             Class activatorClass = Class.forName(className, true, classLoader);
187
188             activateBundle(activatorClass, bundleInfo);
189         }
190         catch(Exception e){
191             Log.e(TAG, e.getMessage(), e);
192         }
193         Log.d(TAG, "Have to register android bundle");
194     }
195     
196     private void activateBundle(Class activatorClass, RcsBundleInfo bundleInfo) throws
197         NoSuchMethodException, InstantiationException, IllegalAccessException, 
198         InvocationTargetException{
199         if(activatorClass == null){
200             throw new IllegalArgumentException(
201                 "activatorClass is null.");
202         }
203         if(bundleInfo == null){
204             throw new IllegalArgumentException(
205                 "bundleInfo is null.");
206         }
207         if(activatorClass!= null){
208             BundleActivator activator = (BundleActivator) activatorClass.
209                     getConstructor(RcsResourceContainerBundleAPI.class, Context.class).
210                     newInstance(this, appContext);
211             activator.activateBundle();
212             activators.put(bundleInfo.getID(), activator);
213             bundleInfo.setActivated(true);
214         }else{
215             Log.e(TAG, "Activator is null.");
216         }
217     }
218
219     /**
220      * API for stopping the Container
221      */
222     public void stopContainer() {
223         // stop all android bundles
224         for(BundleActivator activator :activators.values()){
225             activator.deactivateBundle();
226         }
227         nativeStopContainer();
228     }
229
230     /**
231      * API for getting the list of all bundles in the container
232      *
233      * @return list<RCSBundleInfo> -List of BundleInfo objects each associated
234      *         with a bundle
235      *
236      *         {@link RcsBundleInfo}
237      */
238     public List<RcsBundleInfo> listBundles() {
239         return nativeListBundles();
240     }
241
242     /**
243      * API for adding the bundle to the Container
244      *
245      * @param bundleId
246      *            Id of the Bundle
247      * @param bundleUri
248      *            Uri of the bundle
249      * @param bundlePath
250      *            Path of the bundle
251      * @param activator
252      *            Activation prefix for .so bundles, or activator class name for
253      *            .jar bundles
254      * @param params
255      *            key-value pairs in string form for other Bundle parameters
256      *
257      *            <p>
258      *            It is dynamic configuration
259      */
260     public void addBundle(String bundleId, String bundleUri, String bundlePath,
261             String activator, Map<String, String> params) {
262         if(bundleId == null){
263             throw new IllegalArgumentException(
264                 "bundleId parameter is null.");
265         }
266         if(bundleUri == null){
267             throw new IllegalArgumentException(
268                 "bundleUri is null.");
269         }
270         if(bundlePath == null){
271             throw new IllegalArgumentException(
272                 "bundlePath is null.");
273         }
274         if(activator == null){
275             throw new IllegalArgumentException(
276                 "activator is null.");
277         }
278         nativeAddBundle(bundleId, bundleUri, bundlePath, activator, params);
279     }
280
281     /**
282      * API for removing the bundle from the container
283      *
284      * @param bundleId
285      *            Id of the Bundle
286      *
287      */
288     public void removeBundle(String bundleId) {
289         if(bundleId == null || bundleId.isEmpty()){
290             throw new IllegalArgumentException(
291                 "bundleId parameter is null or empty.");
292         }
293         if(activators.contains(bundleId)){
294             // deactivate android bundle
295             activators.get(bundleId).deactivateBundle();
296         }
297         nativeRemoveBundle(bundleId);
298     }
299
300     /**
301      * API for starting the bundle.
302      *
303      * @param bundleId
304      *            Id of the Bundle
305      *
306      */
307     public void startBundle(String bundleId) {
308         Log.d(TAG, "startBundle");
309         if(bundleId == null || bundleId.isEmpty()){
310             throw new IllegalArgumentException(
311                 "bundleId parameter is null or empty.");
312         }
313         List<RcsBundleInfo> bundles = listBundles();
314
315         for(RcsBundleInfo bundleInfo : bundles){
316             if(bundleInfo.getID().equals(bundleId) && bundleInfo.getPath().endsWith(".apk")){
317                 Log.d(TAG, "Have to start android bundle");
318                 Log.d(TAG, "bundle-id: " + bundleInfo.getID() + ", " + bundleInfo.getPath());
319                 if(bundleInfo.getPath().endsWith(".apk")){
320                     startBundleFromStandaloneApp(bundleInfo);
321                 }else if(bundleInfo.getID().equals(bundleId) &&
322                         bundleInfo.getPath().endsWith(".jar")){ // load classes from library
323                     startBundleFromJar(bundleInfo);
324                 }
325             }else{
326                 nativeStartBundle(bundleId);
327             }
328         }
329     }
330
331     /**
332      * API for Stopping the bundle
333      *
334      * @param bundleId
335      *            Id of the Bundle
336      *
337      */
338     public void stopBundle(String bundleId){
339         if(bundleId == null || bundleId.isEmpty()){
340             throw new IllegalArgumentException(
341                 "bundleId parameter is null or empty.");
342         }
343         nativeStopBundle(bundleId);
344     }
345
346     /**
347      * API for adding the Resource configuration information to the bundle
348      *
349      * @param bundleId
350      *            Id of the Bundle
351      * @param resourceUri
352      *            URI of the resource
353      * @param params
354      *            key-value pairs in string form for other Bundle parameters
355      *
356      */
357     public void addResourceConfig(String bundleId, String resourceUri,
358             Map<String, String> params) {
359         if(bundleId == null || bundleId.isEmpty()){
360             throw new IllegalArgumentException(
361                 "bundleId parameter is null or empty.");
362         }
363         if(resourceUri == null || resourceUri.isEmpty()){
364             throw new IllegalArgumentException(
365                 "resourceUri parameter is null or empty.");
366         }
367         nativeAddResourceConfig(bundleId, resourceUri, params);
368     }
369
370     /**
371      * API for removing the Resource configuration information from the bundle
372      *
373      * @param bundleId
374      *            Id of the Bundle
375      * @param resourceUri
376      *            URI of the resource
377      *
378      */
379     public void removeResourceConfig(String bundleId, String resourceUri) {
380         if(bundleId == null || bundleId.isEmpty()){
381             throw new IllegalArgumentException(
382                 "bundleId parameter is null or empty.");
383         }
384         if(resourceUri == null || resourceUri.isEmpty()){
385             throw new IllegalArgumentException(
386                 "resourceUri parameter is null or empty.");
387         }
388         nativeRemoveResourceConfig(bundleId, resourceUri);
389     }
390
391     /**
392      * API for getting the list of Bundle Resources
393      *
394      * @param bundleId
395      *            Id of the Bundle
396      *
397      * @return List<String> All the bundle resources
398      */
399     public List<String> listBundleResources(String bundleId) {
400         if(bundleId == null || bundleId.isEmpty()){
401             throw new IllegalArgumentException(
402                 "bundleId parameter is null or empty.");
403         }
404         return nativeListBundleResources(bundleId);
405     }
406
407     /**
408      * Registers a bundle resource
409      *
410      * @param bundleId
411      *            Id of the Bundle
412      * @param resource
413      *            resource to be registered
414      */
415     public void registerResource(String bundleId, BundleResource resource){
416         Log.d(TAG, "register Resource");
417         // bundleResources.add(resource);
418         
419         if(bundleId == null || bundleId.isEmpty()){
420                 throw new IllegalArgumentException(
421                 "bundleId parameter is null or empty.");
422         }
423         if(resource == null){
424                 throw new IllegalArgumentException(
425                 "resource parameter is null.");
426         }
427         nativeRegisterBundleResource(resource, resource.getAttributeKeys(), bundleId,
428                         resource.getURI(), resource.getResourceType(),
429                         resource.getName());
430     }
431
432     /**
433      * Returns the bundle configuration for the resources
434      *
435      * @param bundleId
436      *            Id of the Bundle
437      *
438      * @return List<ResourceConfig> All the resource configurations for the given bundle
439      */
440     public List<ResourceConfig> getConfiguredBundleResources(String bundleId) {
441         Log.d(TAG, "getConfiguredBundleResource " + bundleId);
442         Vector<ResourceConfig> configs = new Vector<ResourceConfig>();
443         if(bundleId == null || bundleId.isEmpty()){
444             throw new IllegalArgumentException(
445                 "bundleId parameter is null or empty.");
446         }
447         int configuredResources = getNumberOfConfiguredResources(bundleId);
448         Log.d(TAG, "configured resources " + configuredResources);
449
450         for (int i = 0; i < configuredResources; i++) {
451                 String[] resourceParams = getConfiguredResourceParams(bundleId, i);
452                 ResourceConfig config = new ResourceConfig(resourceParams);
453                 configs.add(config);
454         }
455         return configs;
456     }
457
458     /**
459      * Unregisters a bundle resource
460      *
461      * @param resource
462      *            Resource to be unregistered
463      */
464     public void unregisterResource(BundleResource resource){
465         Log.d(TAG, "unregister Resource");
466         if(resource == null){
467                 throw new IllegalArgumentException(
468                 "resource is null.");
469         }
470         nativeUnregisterBundleResource(resource, resource.getURI());
471     }
472
473     /**
474      * Returns the number of configured resources
475      *
476      * @param bundleId
477      *            Id of the Bundle
478      * @return number of configured resources
479      */
480     public int getNumberOfConfiguredResources(String bundleId){
481         Log.d(TAG, "getNumberOfConfiguredResources");
482         if(bundleId == null || bundleId.isEmpty()){
483             throw new IllegalArgumentException(
484                 "bundleId parameter is null or empty.");
485         }
486         return nativeGetNumberOfConfiguredResources(bundleId);
487     }
488
489     /**
490      * Provides the configured resource parameter
491      *
492      * @param bundleId
493      *            Id of the Bundle
494      * @param resId
495                   Continuous numeric identifier within the bundle
496      * @return resource paramaters such as URI, resource type, name, etc. for the resource
497      */
498     public String[] getConfiguredResourceParams(String bundleId, int resId){
499         Log.d(TAG, "getConfiguredResourceParams");
500         if(bundleId == null || bundleId.isEmpty()){ 
501             throw new IllegalArgumentException(
502                 "bundleId parameter is null or empty.");
503         }
504         if(resId < 0){
505             throw new IllegalArgumentException(
506                 "resId paramater has to be non-negative.");
507         }
508         return nativeGetConfiguredResourceParams(bundleId, resId);
509     }
510 }