Each provider handler is self-destructed if there is no remaining request
[platform/core/context/context-service.git] / src / ProviderLoader.cpp
1 /*
2  * Copyright (c) 2016 Samsung Electronics Co., Ltd.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #include <dlfcn.h>
18 #include <set>
19 #include <Types.h>
20 #include <ContextProvider.h>
21 #include <ProviderList.h>
22 #include "ProviderLoader.h"
23
24 #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof(arr[0]))
25
26 using namespace ctx;
27
28 typedef ContextProvider* (*create_t)(const char *subject);
29
30 std::map<const char*, const char*, CompareSubjectName> ProviderLoader::__providerLibMap;
31
32 ProviderLoader::ProviderLoader() :
33         __soHandle(NULL)
34 {
35 }
36
37 ProviderLoader::~ProviderLoader()
38 {
39         __unload();
40 }
41
42 ContextProvider* ProviderLoader::load(const char *subject)
43 {
44         ProviderLibMap::iterator it = __providerLibMap.find(subject);
45         if (it == __providerLibMap.end()) {
46                 _W("No provider for '%s'", subject);
47                 return NULL;
48         }
49
50         std::string path = LIB_DIRECTORY;
51         path = path + LIB_PREFIX + it->second + LIB_EXTENSION;
52
53         return __load(path.c_str(), subject);
54 }
55
56 ContextProvider* ProviderLoader::__load(const char *soPath, const char *subject)
57 {
58         _SI("Load '%s' from '%s'", subject, soPath);
59
60         __soHandle = dlopen(soPath, RTLD_LAZY | RTLD_GLOBAL);
61         IF_FAIL_RETURN_TAG(__soHandle, NULL, _E, "%s", dlerror());
62
63         create_t create = reinterpret_cast<create_t>(dlsym(__soHandle, "create"));
64         if (!create) {
65                 _E("%s", dlerror());
66                 dlclose(__soHandle);
67                 __soHandle = NULL;
68                 return NULL;
69         }
70
71         ContextProvider *prvd = create(subject);
72         if (!prvd) {
73                 _W("No provider for '%s'", subject);
74                 dlclose(__soHandle);
75                 __soHandle = NULL;
76                 return NULL;
77         }
78
79         return prvd;
80 }
81
82 void ProviderLoader::__unload()
83 {
84         if (!__soHandle)
85                 return;
86
87         dlclose(__soHandle);
88         __soHandle = NULL;
89 }
90
91 bool ProviderLoader::init()
92 {
93         int size = ARRAY_SIZE(subjectLibraryList);
94
95         for (int i = 0; i < size; ++i) {
96                 __providerLibMap[subjectLibraryList[i].subject] = subjectLibraryList[i].library;
97                 _SD("'%s' -> '%s'", subjectLibraryList[i].subject, subjectLibraryList[i].library);
98         }
99
100         return true;
101 }
102
103 bool ProviderLoader::popTriggerTemplate(std::string &subject, int &operation, Json &attribute, Json &option)
104 {
105         static int i = 0;
106         static int size = ARRAY_SIZE(triggerTemplateList);
107
108         if (i == size)
109                 return false;
110
111         subject = triggerTemplateList[i].subject;
112         operation = triggerTemplateList[i].operation;
113         attribute = triggerTemplateList[i].attribute;
114         option = triggerTemplateList[i].option;
115
116         ++i;
117         return true;
118 }