2 * Copyright (c) 2015 Samsung Electronics Co., Ltd.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
19 #include <ProviderTypes.h>
20 #include "access_control/Privilege.h"
22 #include "ProviderHandler.h"
24 #define DELETE_DELAY 20
28 std::map<std::string, ProviderHandler*> ProviderHandler::__instanceMap;
30 ProviderHandler::ProviderHandler(const std::string &subject) :
32 __deleteScheduled(false)
34 _D("Subject: %s", __subject.c_str());
37 ProviderHandler::~ProviderHandler()
39 _D("Subject: %s", __subject.c_str());
41 for (RequestInfo*& info : __subscribeRequests) {
44 __subscribeRequests.clear();
46 for (RequestInfo*& info : __readRequests) {
49 __readRequests.clear();
54 /* TODO: Return proper error code */
55 ProviderHandler* ProviderHandler::getInstance(std::string subject, bool force)
57 InstanceMap::iterator it = __instanceMap.find(subject);
59 if (it != __instanceMap.end())
65 ProviderHandler *handle = new(std::nothrow) ProviderHandler(subject);
66 IF_FAIL_RETURN_TAG(handle, NULL, _E, "Memory allocation failed");
68 if (!handle->__loadProvider()) {
73 __instanceMap[subject] = handle;
78 void ProviderHandler::purge()
80 for (InstanceMap::iterator it = __instanceMap.begin(); it != __instanceMap.end(); ++it) {
84 __instanceMap.clear();
87 int ProviderHandler::unregisterCustomProvider(std::string subject)
89 InstanceMap::iterator it = __instanceMap.find(subject);
90 IF_FAIL_RETURN_TAG(it != __instanceMap.end(), ERR_NOT_SUPPORTED, _E, "'%s' not found", subject.c_str());
92 __instanceMap.erase(subject);
95 _D("'%s' unregistered", subject.c_str());
99 bool ProviderHandler::isSupported()
101 /* If idle, self destruct */
102 __scheduleToDelete();
104 return __provider->isSupported();
107 bool ProviderHandler::isAllowed(const Credentials *creds)
109 /* If idle, self destruct */
110 __scheduleToDelete();
112 IF_FAIL_RETURN(creds, true); /* In case of internal requests */
114 std::vector<const char*> priv;
115 __provider->getPrivilege(priv);
117 for (unsigned int i = 0; i < priv.size(); ++i) {
118 if (!privilege_manager::isAllowed(creds, priv[i]))
125 void ProviderHandler::subscribe(RequestInfo *request)
127 _I(CYAN("'%s' subscribes '%s' (RID-%d)"), request->getClient(), __subject.c_str(), request->getId());
130 int error = __provider->subscribe(request->getDescription().str(), &requestResult);
132 if (!request->reply(error, requestResult) || error != ERR_NONE) {
134 /* If idle, self destruct */
135 __scheduleToDelete();
139 __subscribeRequests.push_back(request);
142 void ProviderHandler::unsubscribe(RequestInfo *request)
144 _I(CYAN("'%s' unsubscribes '%s' (RID-%d)"), request->getClient(), __subject.c_str(), request->getId());
146 /* Search the subscribe request to be removed */
147 auto target = __findRequest(__subscribeRequests, request->getClient(), request->getId());
148 if (target == __subscribeRequests.end()) {
149 _W("Unknown request");
154 /* Keep the pointer to the request found */
155 RequestInfo *reqFound = *target;
157 /* Remove the request from the list */
158 __subscribeRequests.erase(target);
160 /* Check if there exist the same requests */
161 if (__findRequest(__subscribeRequests, reqFound->getDescription()) != __subscribeRequests.end()) {
162 /* Do not stop detecting the subject */
163 _D("A same request from '%s' exists", reqFound->getClient());
164 request->reply(ERR_NONE);
170 /* Stop detecting the subject */
171 int error = __provider->unsubscribe(reqFound->getDescription());
172 request->reply(error);
176 /* If idle, self destruct */
177 __scheduleToDelete();
180 void ProviderHandler::read(RequestInfo *request)
182 _I(CYAN("'%s' reads '%s' (RID-%d)"), request->getClient(), __subject.c_str(), request->getId());
185 int error = __provider->read(request->getDescription().str(), &requestResult);
187 if (!request->reply(error, requestResult) || error != ERR_NONE) {
189 /* If idle, self destruct */
190 __scheduleToDelete();
194 __readRequests.push_back(request);
197 void ProviderHandler::write(RequestInfo *request)
199 _I(CYAN("'%s' writes '%s' (RID-%d)"), request->getClient(), __subject.c_str(), request->getId());
202 request->getDescription().set(NULL, KEY_CLIENT_PKG_ID, request->getPackageId()? request->getPackageId() : "SYSTEM");
203 int error = __provider->write(request->getDescription(), &requestResult);
205 request->reply(error, requestResult);
208 /* If idle, self destruct */
209 __scheduleToDelete();
212 bool ProviderHandler::publish(Json &option, int error, Json &dataUpdated)
214 auto end = __subscribeRequests.end();
215 auto target = __findRequest(__subscribeRequests.begin(), end, option);
217 while (target != end) {
218 if (!(*target)->publish(error, dataUpdated)) {
221 target = __findRequest(++target, end, option);
227 bool ProviderHandler::replyToRead(Json &option, int error, Json &dataRead)
229 auto end = __readRequests.end();
230 auto target = __findRequest(__readRequests.begin(), end, option);
235 while (target != end) {
236 (*target)->reply(error, dummy, dataRead);
238 target = __findRequest(++target, end, option);
241 __readRequests.erase(prev);
244 /* If idle, self destruct */
245 __scheduleToDelete();
250 bool ProviderHandler::__loadProvider()
252 __provider = __loader.load(__subject.c_str());
253 return (__provider != NULL);
256 bool ProviderHandler::__idle()
258 return __subscribeRequests.empty() && __readRequests.empty();
261 void ProviderHandler::__scheduleToDelete()
263 if (__provider->unloadable() && !__deleteScheduled && __idle()) {
264 __deleteScheduled = true;
265 g_timeout_add_seconds(DELETE_DELAY, __deletor, this);
266 _D("Delete scheduled for '%s' (%#x)", __subject.c_str(), this);
270 gboolean ProviderHandler::__deletor(gpointer data)
272 ProviderHandler *handle = static_cast<ProviderHandler*>(data);
274 if (handle->__idle()) {
275 __instanceMap.erase(handle->__subject);
280 handle->__deleteScheduled = false;
284 ProviderHandler::RequestList::iterator
285 ProviderHandler::__findRequest(RequestList &reqList, Json &option)
287 return __findRequest(reqList.begin(), reqList.end(), option);
290 ProviderHandler::RequestList::iterator
291 ProviderHandler::__findRequest(RequestList &reqList, std::string client, int reqId)
293 for (auto it = reqList.begin(); it != reqList.end(); ++it) {
294 if (client == (*it)->getClient() && reqId == (*it)->getId()) {
298 return reqList.end();
301 ProviderHandler::RequestList::iterator
302 ProviderHandler::__findRequest(RequestList::iterator begin, RequestList::iterator end, Json &option)
304 for (auto it = begin; it != end; ++it) {
305 if (option == (*it)->getDescription()) {