a9521a295ff76309c31547f61b11ccddf5312baf
[platform/core/context/context-service.git] / src / ProviderHandler.cpp
1 /*
2  * Copyright (c) 2015 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 <glib.h>
18 #include <Types.h>
19 #include "access_control/Privilege.h"
20 #include "Request.h"
21 #include "ProviderHandler.h"
22
23 using namespace ctx;
24
25 std::map<std::string, ProviderHandler*> ProviderHandler::__instanceMap;
26
27 ProviderHandler::ProviderHandler(const char *subject) :
28         __subject(subject)
29 {
30 }
31
32 ProviderHandler::~ProviderHandler()
33 {
34         for (RequestInfo*& info : __subscribeRequests) {
35                 delete info;
36         }
37         __subscribeRequests.clear();
38
39         for (RequestInfo*& info : __readRequests) {
40                 delete info;
41         }
42         __readRequests.clear();
43
44         delete __provider;
45 }
46
47 /* TODO: Return proper error code */
48 ProviderHandler* ProviderHandler::getInstance(const char *subject, bool force)
49 {
50         InstanceMap::iterator it = __instanceMap.find(subject);
51
52         if (it != __instanceMap.end())
53                 return it->second;
54
55         if (!force)
56                 return NULL;
57
58         ProviderHandler *handle = new(std::nothrow) ProviderHandler(subject);
59         IF_FAIL_RETURN_TAG(handle, NULL, _E, "Memory allocation failed");
60
61         if (!handle->__loadProvider()) {
62                 delete handle;
63                 return NULL;
64         }
65
66         __instanceMap[subject] = handle;
67
68         return handle;
69 }
70
71 void ProviderHandler::purge()
72 {
73         for (InstanceMap::iterator it = __instanceMap.begin(); it != __instanceMap.end(); ++it) {
74                 delete it->second;
75         }
76
77         __instanceMap.clear();
78 }
79
80 bool ProviderHandler::isSupported()
81 {
82         return __provider->isSupported();
83 }
84
85 bool ProviderHandler::isAllowed(const Credentials *creds)
86 {
87         IF_FAIL_RETURN(creds, true);    /* In case of internal requests */
88
89         std::vector<const char*> priv;
90         __provider->getPrivilege(priv);
91
92         for (unsigned int i = 0; i < priv.size(); ++i) {
93                 if (!privilege_manager::isAllowed(creds, priv[i]))
94                         return false;
95         }
96
97         return true;
98 }
99
100 void ProviderHandler::subscribe(RequestInfo *request)
101 {
102         _I(CYAN("'%s' subscribes '%s' (RID-%d)"), request->getClient(), __subject, request->getId());
103
104         Json requestResult;
105         int error = __provider->subscribe(request->getDescription().str(), &requestResult);
106
107         if (!request->reply(error, requestResult) || error != ERR_NONE) {
108                 delete request;
109                 return;
110         }
111
112         __subscribeRequests.push_back(request);
113 }
114
115 void ProviderHandler::unsubscribe(RequestInfo *request)
116 {
117         _I(CYAN("'%s' unsubscribes '%s' (RID-%d)"), request->getClient(), __subject, request->getId());
118
119         /* Search the subscribe request to be removed */
120         auto target = __findRequest(__subscribeRequests, request->getClient(), request->getId());
121         if (target == __subscribeRequests.end()) {
122                 _W("Unknown request");
123                 delete request;
124                 return;
125         }
126
127         /* Keep the pointer to the request found */
128         RequestInfo *reqFound = *target;
129
130         /* Remove the request from the list */
131         __subscribeRequests.erase(target);
132
133         /* Check if there exist the same requests */
134         if (__findRequest(__subscribeRequests, reqFound->getDescription()) != __subscribeRequests.end()) {
135                 /* Do not stop detecting the subject */
136                 _D("A same request from '%s' exists", reqFound->getClient());
137                 request->reply(ERR_NONE);
138                 delete request;
139                 delete reqFound;
140                 return;
141         }
142
143         /* Stop detecting the subject */
144         int error = __provider->unsubscribe(reqFound->getDescription());
145         request->reply(error);
146         delete request;
147         delete reqFound;
148 }
149
150 void ProviderHandler::read(RequestInfo *request)
151 {
152         _I(CYAN("'%s' reads '%s' (RID-%d)"), request->getClient(), __subject, request->getId());
153
154         Json requestResult;
155         int error = __provider->read(request->getDescription().str(), &requestResult);
156
157         if (!request->reply(error, requestResult) || error != ERR_NONE) {
158                 delete request;
159                 return;
160         }
161
162         __readRequests.push_back(request);
163 }
164
165 void ProviderHandler::write(RequestInfo *request)
166 {
167         _I(CYAN("'%s' writes '%s' (RID-%d)"), request->getClient(), __subject, request->getId());
168
169         Json requestResult;
170         int error = __provider->write(request->getDescription(), &requestResult);
171
172         request->reply(error, requestResult);
173         delete request;
174 }
175
176 bool ProviderHandler::publish(Json &option, int error, Json &dataUpdated)
177 {
178         auto end = __subscribeRequests.end();
179         auto target = __findRequest(__subscribeRequests.begin(), end, option);
180
181         while (target != end) {
182                 if (!(*target)->publish(error, dataUpdated)) {
183                         return false;
184                 }
185                 target = __findRequest(++target, end, option);
186         }
187
188         return true;
189 }
190
191 bool ProviderHandler::replyToRead(Json &option, int error, Json &dataRead)
192 {
193         auto end = __readRequests.end();
194         auto target = __findRequest(__readRequests.begin(), end, option);
195         auto prev = target;
196
197         Json dummy;
198
199         while (target != end) {
200                 (*target)->reply(error, dummy, dataRead);
201                 prev = target;
202                 target = __findRequest(++target, end, option);
203
204                 delete *prev;
205                 __readRequests.erase(prev);
206         }
207
208         return true;
209 }
210
211 bool ProviderHandler::__loadProvider()
212 {
213         __provider = __loader.load(__subject);
214         return (__provider != NULL);
215 }
216
217 ProviderHandler::RequestList::iterator
218 ProviderHandler::__findRequest(RequestList &reqList, Json &option)
219 {
220         return __findRequest(reqList.begin(), reqList.end(), option);
221 }
222
223 ProviderHandler::RequestList::iterator
224 ProviderHandler::__findRequest(RequestList &reqList, std::string client, int reqId)
225 {
226         for (auto it = reqList.begin(); it != reqList.end(); ++it) {
227                 if (client == (*it)->getClient() && reqId == (*it)->getId()) {
228                         return it;
229                 }
230         }
231         return reqList.end();
232 }
233
234 ProviderHandler::RequestList::iterator
235 ProviderHandler::__findRequest(RequestList::iterator begin, RequestList::iterator end, Json &option)
236 {
237         for (auto it = begin; it != end; ++it) {
238                 if (option == (*it)->getDescription()) {
239                         return it;
240                 }
241         }
242         return end;
243 }