7ee27e4f68bf75ded0e40a9d3f913364bd925795
[platform/framework/native/appfw.git] / src / app / FApp_MapDataControlImpl.cpp
1 //
2 // Copyright (c) 2012 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 /**
18  * @file        FApp_MapDataControlImpl.cpp
19  * @brief       This is the implementation for the %_MapDataControlImpl class.
20  */
21
22 #include <typeinfo>
23 #include <unique_ptr.h>
24
25 #include <appsvc/appsvc.h>
26
27 #include <FBaseInteger.h>
28 #include <FBaseString.h>
29 #include <FBaseColLinkedList.h>
30 #include <FBaseRtIEventArg.h>
31 #include <FIoFile.h>
32 #include <FAppMapDataControl.h>
33 #include <FAppIMapDataControlResponseListener.h>
34
35 #include <FBaseSysLog.h>
36
37 #include "FApp_AppControlManager.h"
38 #include "FApp_MapDataControlImpl.h"
39 #include "FApp_AppArg.h"
40 #include "FApp_DataControlManager.h"
41
42 using namespace std;
43
44 using namespace Tizen::Base;
45 using namespace Tizen::Base::Collection;
46 using namespace Tizen::Base::Runtime;
47 using namespace Tizen::App;
48 using namespace Tizen::Io;
49
50 namespace Tizen { namespace App
51 {
52
53 static const int MAX_REQUEST_COUNT = 128;
54 static const int REQUEST_THRESHOLD = 100;
55 static const int _MAX_ARGUMENT_SIZE = 16384; // 16KB
56
57 class _MapDataControlEventArg
58         : public IEventArg
59 {
60 public:
61                 _MapDataControlEventArg(_DataControlRequestType requestType, RequestId reqId, String providerId, String dataId,
62                                 IList* pResultValueList, bool providerResult, String* pErrorMsg)
63                         : __requestType(requestType)
64                         , __reqId(reqId)
65                         , __providerId(providerId)
66                         , __dataId(dataId)
67                         , __pResultValueList(pResultValueList)
68                         , __providerResult(providerResult)
69                         , __pErrorMsg(pErrorMsg)
70                 {
71                 }
72                 ~_MapDataControlEventArg(void)
73                 {
74                         if (__pResultValueList)
75                         {
76                                 __pResultValueList->RemoveAll(true);
77                                 delete __pResultValueList;
78                         }
79                         delete __pErrorMsg;
80                 }
81
82                 _DataControlRequestType __requestType;
83                 RequestId __reqId;
84                 String __providerId;
85                 String __dataId;
86                 IList* __pResultValueList;
87                 bool __providerResult;
88                 String* __pErrorMsg;
89 };
90
91 class _MapDataControlEvent
92         : public Event
93 {
94 protected:
95         virtual void FireImpl(IEventListener& listener, const IEventArg& arg);
96 };
97
98 void
99 _MapDataControlEvent::FireImpl(IEventListener& listener, const IEventArg& arg)
100 {
101         const _MapDataControlEventArg* pArg = dynamic_cast<const _MapDataControlEventArg*>(&arg);
102         if (pArg != null)
103         {
104                 IMapDataControlResponseListener* pListener = dynamic_cast<IMapDataControlResponseListener*> (&listener);
105                 if (pListener != null)
106                 {
107                         switch (pArg->__requestType)
108                         {
109                         case _DATACONTROL_REQUEST_TYPE_MAP_QUERY:
110                                 pListener->OnMapDataControlGetValueResponseReceived(pArg->__reqId, pArg->__providerId, pArg->__dataId,
111                                                 *(pArg->__pResultValueList), pArg->__providerResult, pArg->__pErrorMsg);
112                                 break;
113                         case _DATACONTROL_REQUEST_TYPE_MAP_INSERT:
114                                 pListener->OnMapDataControlAddValueResponseReceived(pArg->__reqId, pArg->__providerId, pArg->__dataId,
115                                                  pArg->__providerResult, pArg->__pErrorMsg);
116                                 break;
117                         case _DATACONTROL_REQUEST_TYPE_MAP_UPDATE:
118                                 pListener->OnMapDataControlSetValueResponseReceived(pArg->__reqId, pArg->__providerId, pArg->__dataId,
119                                                 pArg->__providerResult, pArg->__pErrorMsg);
120                                 break;
121                         case _DATACONTROL_REQUEST_TYPE_MAP_DELETE:
122                                 pListener->OnMapDataControlRemoveValueResponseReceived(pArg->__reqId, pArg->__providerId, pArg->__dataId,
123                                                 pArg->__providerResult, pArg->__pErrorMsg);
124                                 break;
125                         default:
126                                 break;
127                         }
128                 }
129         }
130 }
131
132 // private
133 _MapDataControlImpl::_MapDataControlImpl(void)
134         : __access(_DATACONTROL_ACCESS_UNDEFINED)
135         , __pPreviousListener(null)
136         , __pMapDataControlEvent(null)
137 {
138 }
139
140 _MapDataControlImpl::~_MapDataControlImpl(void)
141 {
142         delete __pMapDataControlEvent;
143
144         _DataControlManager* pDcMgr = _DataControlManager::GetInstance();
145
146         IEnumerator* pEnum = __pRequestList->GetEnumeratorN();
147         while (pEnum->MoveNext() == E_SUCCESS)
148         {
149                 Integer* pReqId = dynamic_cast< Integer* >(pEnum->GetCurrent());
150                 if (pReqId != null)
151                 {
152                         pDcMgr->RemoveRequestInfo(*pReqId);
153                 }
154         }
155         delete __pRequestList;
156 }
157
158 _MapDataControlImpl*
159 _MapDataControlImpl::GetInstance(MapDataControl& dc)
160 {
161         return dc.__pMapDataControlImpl;
162 }
163
164 const _MapDataControlImpl*
165 _MapDataControlImpl::GetInstance(const MapDataControl& dc)
166 {
167         return dc.__pMapDataControlImpl;
168 }
169
170 result
171 _MapDataControlImpl::StartMapDataControl(int type, const IList* pDataList, int* pReq)
172 {
173         Integer* pReqId = null;
174         _DataControlRequestInfo* pReqInfo = null;
175         result r = E_SUCCESS;
176
177         int req = -1;
178         _DataControlManager* pDcMgr = _DataControlManager::GetInstance();
179
180         // Check the request count of DataControl operation
181         int count = pDcMgr->GetRequestCount();
182         SysLog(NID_APP, "Current launch request count: %d", count);
183
184         if (count > REQUEST_THRESHOLD)
185         {
186                 _AppManagerImpl* pImpl = _AppManagerImpl::GetInstance();
187
188                 // Clear the request queue if the provider is terminated
189                 if (!pImpl->IsRunning(__appId))
190                 {
191                         SysLog(NID_APP, "The request queue is cleared due to the invalid provider.");
192
193                         pDcMgr->RemoveAllRequests();
194                 }
195         }
196
197         SysTryReturnResult(NID_APP, count < MAX_REQUEST_COUNT, E_MAX_EXCEEDED, "The number of requests has exceeded the maximum limit.");
198
199         _AppArg* pArg = new(std::nothrow) _AppArg; // XXX: pArg will be released in _AppManagerImpl::LaunchApp().
200         SysTryReturnResult(NID_APP, pArg != null, E_OUT_OF_MEMORY, "The memory is insufficient.");
201
202         pArg->Construct(*this, static_cast <_DataControlRequestType>(type), pDataList);
203
204         _AppControlManager* pAppManagerImpl = _AppControlManager::GetInstance();
205
206         if (__pMapDataControlEvent)
207         {
208                 // reqId is system-wide id because the bundle is system-wide.
209 #if 0
210                 _AppControlManager::_RequestGuard reqObj = _AppControlManager::_RequestGuard(*pAppManagerImpl, pArg, MapDataControlCallback, __pMapDataControlEvent, -1);
211                 req = reqObj.GetRequestNumber();
212 #else
213                 _DataControlManager* pDcMgr = _DataControlManager::GetInstance();
214                 _AppControlManager::_RequestGuard reqObj = _AppControlManager::_RequestGuard(*pAppManagerImpl, pArg, MapDataControlCallback, pDcMgr, -1);
215                 req = reqObj.GetRequestNumber();
216 #endif
217                 pReqId = new (std::nothrow) Integer(req);
218                 SysTryCatch(NID_APP, pReqId != null, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY,
219                                 "[E_OUT_OF_MEMORY] The memory is insufficient");
220
221                 pReqInfo = new (std::nothrow) _DataControlRequestInfo(__pMapDataControlEvent);
222                 SysTryCatch(NID_APP, pReqInfo != null, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY,
223                                 "[E_OUT_OF_MEMORY] The memory is insufficient");
224                 pReqInfo->SetMapDataControlImpl(this);
225
226                 r = pDcMgr->AddRequestInfo(pReqId, pReqInfo);
227                 SysTryCatch(NID_APP, !IsFailed(r), r = E_SYSTEM, E_SYSTEM, "[%s] Failed to add request info", GetErrorMessage(r));
228
229                 r = pAppManagerImpl->LaunchApp(__appId, pArg, req);
230                 if (IsFailed(r))
231                 {
232                         SysPropagate(NID_APP, r);
233                         reqObj.Invalidate();
234                         pDcMgr->RemoveRequestInfo(*pReqId);
235                         return r;
236                 }
237
238                 __pRequestList->Add(new (std::nothrow) Integer(req));
239
240                 if (pReq)
241                 {
242                         *pReq = req;
243                 }
244         }
245         else
246         {
247                 r = pAppManagerImpl->LaunchApp(__appId, pArg);
248                 SysTryCatch(NID_APP, !IsFailed(r), , r, "[%s] Propagating to caller...", GetErrorMessage(r));
249                 delete pArg;
250         }
251
252         return E_SUCCESS;
253
254 CATCH:
255         delete pArg;
256         delete pReqId;
257         delete pReqInfo;
258         return r;
259 }
260
261 result
262 _MapDataControlImpl::GetValue(const String& dataId, const String& key,
263                 RequestId& reqId, int pageNo, int countPerPage)
264 {
265         SysTryReturnResult(NID_APP, pageNo > 0, E_INVALID_ARG, "The specified pageNo parameter is less than 1");
266         SysTryReturnResult(NID_APP, countPerPage > 0, E_INVALID_ARG, "The specified countPerPage parameter is less than 1");
267         SysTryReturnResult(NID_APP, (__access & _DATACONTROL_ACCESS_READ) > 0, E_ILLEGAL_ACCESS,
268                         "The GetValue query is not permitted by DataControl provider.");
269
270         String* pPageNo = null;
271         String* pCountPerPage = null;
272         int id = 0;
273         result r = E_SUCCESS;
274
275         ArrayList* pArgList = new ArrayList();
276         pArgList->Construct();
277
278         pArgList->Add(*(new String(dataId)));
279         pArgList->Add(*(new String(key)));
280         long long argSize = dataId.GetLength() * sizeof(wchar_t);
281         argSize += key.GetLength() * sizeof(wchar_t);
282         SysTryCatch(NID_APP, argSize <= _MAX_ARGUMENT_SIZE, r = E_MAX_EXCEEDED, E_MAX_EXCEEDED,
283                         "[E_MAX_EXCEEDED] The size of sending argument (%lld) exceeds the maximum limit.", argSize);
284
285         pPageNo = new (std::nothrow) String();
286         pPageNo->Append(pageNo);
287         pArgList->Add(*pPageNo);
288
289         pCountPerPage = new (std::nothrow) String();
290         pCountPerPage->Append(countPerPage);
291         pArgList->Add(*pCountPerPage);
292
293         r = StartMapDataControl(_DATACONTROL_REQUEST_TYPE_MAP_QUERY, pArgList, &id);
294         SysTryCatch(NID_APP, !IsFailed(r), , r, "[%s] Propagating to caller...", GetErrorMessage(r));
295
296         reqId = static_cast< RequestId >(id);
297
298         SysLog(NID_APP, "[DC_CALLER_SEND] data: %ls, key: %ls, req: %d, pageNo: %d, countPerPage: %d",
299                         dataId.GetPointer(), key.GetPointer(), reqId, pageNo, countPerPage);
300
301         // fall through
302 CATCH:
303         pArgList->RemoveAll(true);
304         delete pArgList;
305
306         return r;
307 }
308
309 result
310 _MapDataControlImpl::MapDataControlCallback(void* data, _AppArg* pArg, _AppArg* pResArg, service_result_e res, int prop, int option)
311 {
312         ArrayList* pResultList = null;
313         String version;
314         String* pResult = null;
315         String* pProviderId = null;
316         String* pDataId = null;
317         String* pErrorMessage = null;
318         String* pErrorMsg = null;
319         String* pResultCount = null;
320         String* pPath = null;
321         ArrayList* pResultValueList = null;
322         int resultCount = 0;
323         int requestType = 0;
324         int reqId = 0;
325         int launchReqId = 0;
326         int providerRes = 0;
327         bool providerResult = true;
328         //bundle* origBundle = null;
329         bundle* resBundle = null;
330         _MapDataControlEventArg* pEventArg = null;
331         const char* p = null;
332         result r = E_SUCCESS;
333
334         SysTryReturnResult(NID_APP, pResArg != null, E_INVALID_ARG, "Empty result callback.");
335         SysLog(NID_APP, "appsvc result value: %d", res);
336
337         resBundle = pResArg->GetBundle();
338         if (resBundle)
339         {
340                 p = appsvc_get_data(resBundle, OSP_K_REQUEST_ID);
341                 SysTryCatch(NID_APP, p, r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] invalid bundle");
342                 reqId = atoi(p);
343                 Integer key(reqId);
344
345                 _DataControlManager* pDcMgr = static_cast< _DataControlManager* >(data);
346                 _DataControlRequestInfo* pReqInfo = pDcMgr->GetRequestInfo(key);
347                 if (pReqInfo == null)
348                 {
349                         SysLog(NID_APP, "No request info of reqId %d", reqId);
350                         return E_SUCCESS;
351                 }
352
353                 _MapDataControlEvent* pMapDataControlEvent = dynamic_cast< _MapDataControlEvent* >(pReqInfo->GetEvent());
354                 SysTryCatch(NID_APP, pMapDataControlEvent != null, r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] invalid request info");
355
356                 pDcMgr->RemoveRequestInfo(key);
357
358                 _MapDataControlImpl* pDcImpl = pReqInfo->GetMapDataControlImpl();
359                 SysTryCatch(NID_APP, pDcImpl != null, r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] invalid request info");
360                 pDcImpl->__pRequestList->Remove(key);
361
362                 // Remove the request from the queue
363                 SysLog(NID_APP, "Remove the request, req: %d", reqId);
364
365                 if (pMapDataControlEvent != null && typeid(pMapDataControlEvent) == typeid(_MapDataControlEvent*))
366                 {
367
368                         // result list
369                         pResultList = _AppArg::GetListN(resBundle, OSP_K_ARG);
370                         SysTryCatch(NID_APP, pResultList, r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] invalid result");
371
372                         pResult = dynamic_cast <String*>(pResultList->GetAt(0)); // result list[0]
373                         SysTryCatch(NID_APP, pResult, r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] invalid result");
374                         Integer::Parse(*pResult, providerRes);
375                         providerResult = static_cast< bool >(providerRes);
376
377                         pErrorMessage = dynamic_cast< String* >(pResultList->GetAt(1)); // result list[1]
378                         SysTryCatch(NID_APP, pErrorMessage, r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] invalid result");
379                         pErrorMsg = new (std::nothrow) String(*pErrorMessage);
380                         SysTryCatch(NID_APP, pErrorMsg, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY,
381                                         "[E_OUT_OF_MEMORY] The memory is insufficient.");
382
383                         // request info
384                         //origBundle = pArg->GetBundle();
385
386                         p = appsvc_get_data(resBundle, OSP_K_DATACONTROL_REQUEST_TYPE);
387                         SysTryCatch(NID_APP, p, r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] invalid bundle");
388                         requestType = atoi(p);
389
390                         p = appsvc_get_data(resBundle, OSP_K_DATACONTROL_PROVIDER);
391                         SysTryCatch(NID_APP, p, r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] invalid bundle");
392                         pProviderId = new (std::nothrow) String(p);
393                         SysTryCatch(NID_APP, pProviderId, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY,
394                                         "[E_OUT_OF_MEMORY] The memory is insufficient.");
395
396                         p = appsvc_get_data(resBundle, OSP_K_DATACONTROL_DATA);
397                         SysTryCatch(NID_APP, p, r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] invalid bundle");
398                         pDataId = new (std::nothrow) String(p);
399                         SysTryCatch(NID_APP, pDataId, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY,
400                                         "[E_OUT_OF_MEMORY] The memory is insufficient.");
401
402                         version = pResArg->GetValue(OSP_K_DATACONTROL_PROTOCOL_VERSION);
403
404                         SysSecureLog(NID_APP, "[DC_CALLER_RECV] version: %ls, provider result: %ld, requestType: %d, req: %d, provider: %ls, data: %ls, errorMsg: %ls",
405                                         version.GetPointer(), providerRes, requestType, reqId, pProviderId->GetPointer(), pDataId->GetPointer(), pErrorMsg->GetPointer());
406
407                         switch (static_cast< _DataControlRequestType >(requestType))
408                         {
409                         case _DATACONTROL_REQUEST_TYPE_MAP_QUERY:
410                         {
411                                 pResultValueList = new (std::nothrow) ArrayList(SingleObjectDeleter);
412                                 SysTryCatch(NID_APP, pResultValueList, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY,
413                                                 "[E_OUT_OF_MEMORY] The memory is insufficient.");
414
415                                 if (providerResult == true)
416                                 {
417                                         pResultCount = dynamic_cast< String* >(pResultList->GetAt(2)); // result list[2]
418                                         SysTryCatch(NID_APP, pResultCount, delete pResultValueList, E_SYSTEM, "[E_SYSTEM] invalid result");
419                                         Integer::Parse(*pResultCount, resultCount);
420                                         SysLog(NID_APP, "[DC_CALLER_RECV] result count: %d", resultCount);
421
422                                         if (resultCount > 0)
423                                         {
424                                                 if (version == L"ver_2.1.0.1" || version == L"ver_2.1.0.2" || version == L"ver_2.1.0.3")
425                                                 {
426                                                         pPath = dynamic_cast< String* >(pResultList->GetAt(3)); // result list[3]
427                                                         SysTryCatch(NID_APP, pPath, delete pResultValueList, E_SYSTEM, "[E_SYSTEM] invalid result");
428                                                         SysLog(NID_APP, "[DC_CALLER_RECV] path: %ls", pPath->GetPointer());
429
430                                                         unique_ptr< File > pFile(new (std::nothrow) File());
431                                                         SysTryCatch(NID_APP, pFile, delete pResultValueList, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
432
433                                                         r = pFile->Construct(*pPath, "r");
434                                                         SysTryCatch(NID_APP, !IsFailed(r), delete pResultValueList, r, "[%s] Failed to open result set (%ls)",
435                                                                         GetErrorMessage(r), pPath->GetPointer());
436
437                                                         while (resultCount)
438                                                         {
439                                                                 int length = 0;
440                                                                 int ret = pFile->Read(&length, sizeof(int));
441                                                                 SysTryCatch(NID_APP, ret, delete pResultValueList, E_SYSTEM,
442                                                                                 "[E_SYSTEM] Failed to read data from the result set of data control provider.");
443
444                                                                 char* pValue = new (std::nothrow) char[length + 1];
445                                                                 SysTryCatch(NID_APP, pValue, delete pResultValueList, E_OUT_OF_MEMORY,
446                                                                                 "[E_OUT_OF_MEMORY] The memory is insufficient.");
447
448                                                                 ret = pFile->Read(pValue, length);
449                                                                 if (ret == 0)
450                                                                 {
451                                                                         SysLogException(NID_APP, E_SYSTEM,
452                                                                                         "[E_SYSTEM] Failed to read data from the result set of data control provider.");
453                                                                         delete pResultValueList;
454                                                                         delete[] pValue;
455                                                                         goto CATCH;
456                                                                 }
457                                                                 pValue[length] = '\0';
458
459                                                                 pResultValueList->Add(new (std::nothrow) String(pValue));
460                                                                 delete[] pValue;
461                                                                 --resultCount;
462                                                         }
463                                                 }
464                                                 else
465                                                 {
466                                                         int index = 3;
467                                                         while (resultCount)
468                                                         {
469                                                                 String* pValue = dynamic_cast< String* >(pResultList->GetAt(index)); // result list[3] ~
470                                                                 SysTryCatch(NID_APP, pValue, delete pResultValueList, E_SYSTEM, "[E_SYSTEM] invalid result");
471
472                                                                 pResultValueList->Add((new (std::nothrow) String(*pValue)));
473                                                                 --resultCount;
474                                                                 ++index;
475                                                         }
476                                                 }
477                                         }
478
479                                         if (pPath)
480                                         {
481                                                 r = File::Remove(*pPath);
482                                                 SysTryLog(NID_APP, !IsFailed(r), "Failed to remove result: %ls", pPath->GetPointer());
483                                         }
484                                 }
485
486                                 pEventArg = new (std::nothrow) _MapDataControlEventArg(_DATACONTROL_REQUEST_TYPE_MAP_QUERY, static_cast <RequestId>(reqId),
487                                                 *pProviderId, *pDataId, pResultValueList, providerResult, pErrorMsg);
488                                 SysTryCatch(NID_APP, pEventArg != null, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
489                                 pMapDataControlEvent->Fire(*pEventArg);
490
491                                 break;
492                         }
493                         case _DATACONTROL_REQUEST_TYPE_MAP_INSERT:
494                         {
495                                 pEventArg = new (std::nothrow) _MapDataControlEventArg(_DATACONTROL_REQUEST_TYPE_MAP_INSERT, static_cast <RequestId>(reqId),
496                                                 *pProviderId, *pDataId, null, providerResult, pErrorMsg);
497                                 SysTryCatch(NID_APP, pEventArg != null, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
498                                 pMapDataControlEvent->Fire(*pEventArg);
499                                 break;
500                         }
501                         case _DATACONTROL_REQUEST_TYPE_MAP_UPDATE:
502                         {
503                                 pEventArg = new (std::nothrow) _MapDataControlEventArg(_DATACONTROL_REQUEST_TYPE_MAP_UPDATE, static_cast <RequestId>(reqId),
504                                                 *pProviderId, *pDataId, null, providerResult, pErrorMsg);
505                                 SysTryCatch(NID_APP, pEventArg != null, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
506                                 pMapDataControlEvent->Fire(*pEventArg);
507                                 break;
508                         }
509                         case _DATACONTROL_REQUEST_TYPE_MAP_DELETE:
510                         {
511                                 pEventArg = new (std::nothrow) _MapDataControlEventArg(_DATACONTROL_REQUEST_TYPE_MAP_DELETE, static_cast <RequestId>(reqId),
512                                                 *pProviderId, *pDataId, null, providerResult, pErrorMsg);
513                                 SysTryCatch(NID_APP, pEventArg != null, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
514                                 pMapDataControlEvent->Fire(*pEventArg);
515                                 break;
516                         }
517                         default:
518                                 break;
519                         }
520
521                         pResultList->RemoveAll(true);
522                         delete pResultList;
523                         delete pProviderId;
524                 }
525         }
526
527         p = appsvc_get_data(pArg->GetBundle(), OSP_K_REQUEST_ID);
528         SysTryCatch(NID_APP, p, r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] invalid bundle");
529         launchReqId = atoi(p);
530
531         return E_SUCCESS;
532
533 CATCH:
534         if (pResultList)
535         {
536                 pResultList->RemoveAll(true);
537                 delete pResultList;
538         }
539         delete pProviderId;
540
541         return r;
542 }
543
544 result
545 _MapDataControlImpl::AddValue(const String& dataId, const String& key,
546                 const String& value, RequestId& reqId)
547 {
548         SysTryReturnResult(NID_APP, (__access & _DATACONTROL_ACCESS_WRITE) > 0, E_ILLEGAL_ACCESS,
549                         "The AddValue query is not permitted by DataControl provider.");
550
551         int id = 0;
552         result r = E_SUCCESS;
553
554         ArrayList* pArgList = null;
555         pArgList = new ArrayList();
556         pArgList->Construct();
557
558         pArgList->Add(*(new String(dataId)));
559         pArgList->Add(*(new String(key)));
560         pArgList->Add(*(new String(value)));
561         long long argSize = dataId.GetLength() * sizeof(wchar_t);
562         argSize += key.GetLength() * sizeof(wchar_t);
563         argSize += value.GetLength() * sizeof(wchar_t);
564         SysTryCatch(NID_APP, argSize <= _MAX_ARGUMENT_SIZE, r = E_MAX_EXCEEDED, E_MAX_EXCEEDED,
565                         "[E_MAX_EXCEEDED] The size of sending argument (%lld) exceeds the maximum limit.", argSize);
566
567         r = StartMapDataControl(_DATACONTROL_REQUEST_TYPE_MAP_INSERT, pArgList, &id);
568         SysTryCatch(NID_APP, !IsFailed(r), , r, "[%s] Propagating to caller...", GetErrorMessage(r));
569
570         reqId = static_cast< RequestId >(id);
571
572         SysLog(NID_APP, "[DC_CALLER_SEND] data: %ls, key: %ls, value: %ls, req: %d",
573                         dataId.GetPointer(), key.GetPointer(), value.GetPointer(), reqId);
574
575         // fall through
576 CATCH:
577         pArgList->RemoveAll(true);
578         delete pArgList;
579
580         return r;
581 }
582
583 result
584 _MapDataControlImpl::SetValue(const String& dataId, const String& key,
585                 const String& oldValue, const String& newValue, RequestId& reqId)
586 {
587         SysTryReturnResult(NID_APP, (__access & _DATACONTROL_ACCESS_WRITE) > 0, E_ILLEGAL_ACCESS,
588                         "The SetValue query is not permitted by DataControl provider.");
589
590         int id = 0;
591         result r = E_SUCCESS;
592
593         ArrayList* pArgList = null;
594         pArgList = new ArrayList();
595         pArgList->Construct();
596
597         pArgList->Add(*(new String(dataId)));
598         pArgList->Add(*(new String(key)));
599         pArgList->Add(*(new String(oldValue)));
600         pArgList->Add(*(new String(newValue)));
601         long long argSize = dataId.GetLength() * sizeof(wchar_t);
602         argSize += key.GetLength() * sizeof(wchar_t);
603         argSize += oldValue.GetLength() * sizeof(wchar_t);
604         argSize += newValue.GetLength() * sizeof(wchar_t);
605         SysTryCatch(NID_APP, argSize <= _MAX_ARGUMENT_SIZE, r = E_MAX_EXCEEDED, E_MAX_EXCEEDED,
606                         "[E_MAX_EXCEEDED] The size of sending argument (%lld) exceeds the maximum limit.", argSize);
607
608         r = StartMapDataControl(_DATACONTROL_REQUEST_TYPE_MAP_UPDATE, pArgList, &id);
609         SysTryCatch(NID_APP, !IsFailed(r), , r, "[%s] Propagating to caller...", GetErrorMessage(r));
610
611         reqId = static_cast< RequestId >(id);
612
613         SysLog(NID_APP, "[DC_CALLER_SEND] data: %ls, key: %ls, oldValue: %ls, newValue: %ls, req: %d",
614                         dataId.GetPointer(), key.GetPointer(), oldValue.GetPointer(), newValue.GetPointer(), reqId);
615
616         // fall through
617 CATCH:
618         pArgList->RemoveAll(true);
619         delete pArgList;
620
621         return r;
622 }
623
624 result
625 _MapDataControlImpl::RemoveValue(const String& dataId, const String& key,
626                 const String& value, RequestId& reqId)
627 {
628         SysTryReturnResult(NID_APP, (__access & _DATACONTROL_ACCESS_WRITE) > 0, E_ILLEGAL_ACCESS,
629                         "The RemoveValue query is not permitted by DataControl provider.");
630
631         int id = 0;
632         result r = E_SUCCESS;
633
634         ArrayList* pArgList = null;
635         pArgList = new ArrayList();
636         pArgList->Construct();
637
638         pArgList->Add(*(new String(dataId)));
639         pArgList->Add(*(new String(key)));
640         pArgList->Add(*(new String(value)));
641         long long argSize = dataId.GetLength() * sizeof(wchar_t);
642         argSize += key.GetLength() * sizeof(wchar_t);
643         argSize += value.GetLength() * sizeof(wchar_t);
644         SysTryCatch(NID_APP, argSize <= _MAX_ARGUMENT_SIZE, r = E_MAX_EXCEEDED, E_MAX_EXCEEDED,
645                         "[E_MAX_EXCEEDED] The size of sending argument (%lld) exceeds the maximum limit.", argSize);
646
647         r = StartMapDataControl(_DATACONTROL_REQUEST_TYPE_MAP_DELETE, pArgList, &id);
648         SysTryCatch(NID_APP, !IsFailed(r), , r, "[%s] Propagating to caller...", GetErrorMessage(r));
649
650         reqId = static_cast< RequestId >(id);
651
652         SysLog(NID_APP, "[DC_CALLER_SEND] data: %ls, key: %ls, value: %ls, req: %d",
653                         dataId.GetPointer(), key.GetPointer(), value.GetPointer(), reqId);
654
655         // fall through
656 CATCH:
657         pArgList->RemoveAll(true);
658         delete pArgList;
659
660         return r;
661 }
662
663 result
664 _MapDataControlImpl::SetMapDataControlResponseListener(IMapDataControlResponseListener* pListener)
665 {
666         result r = E_SUCCESS;
667
668         if (__pPreviousListener != null)
669         {
670                 r =  __pMapDataControlEvent->RemoveListener(*__pPreviousListener);
671                 SysTryReturnResult(NID_APP, !IsFailed(r), E_SYSTEM, "Remove listener failed.");
672                  __pPreviousListener = null;
673         }
674
675         if (pListener != null)
676         {
677                 r =  __pMapDataControlEvent->AddListener(*pListener);
678                 if (IsFailed(r))
679                 {
680                         switch (r)
681                         {
682                         case E_OBJ_ALREADY_EXIST:
683                                 return E_SUCCESS;
684                         case E_INVALID_OPERATION:
685                                 SysLogException(NID_APP, E_SYSTEM, "[E_SYSTEM] The thread setting the listener is worker thread.");
686                                 return E_SYSTEM;
687                         default:
688                                 SysLogException(NID_APP, r, "[%s] Propagating to caller...", GetErrorMessage(r));
689                                 return r;
690                         }
691                 }
692         }
693
694         __pPreviousListener = pListener;
695
696         return E_SUCCESS;
697 }
698
699 // private
700 MapDataControl*
701 _MapDataControlImpl::CreateMapDataControl(const AppId& appId, const String& providerId, const String& access)
702 {
703         unique_ptr<MapDataControl> pDc(new (std::nothrow) MapDataControl);
704         SysTryReturn(NID_APP, pDc != null, null, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient");
705
706         _MapDataControlImpl* pDcImpl = _MapDataControlImpl::GetInstance(*pDc);
707         pDcImpl->__appId = appId;
708         pDcImpl->__providerId = providerId;
709         unique_ptr<_MapDataControlEvent> pMapDataControlEvent(new (std::nothrow) _MapDataControlEvent);
710         SysTryReturn(NID_IO, pMapDataControlEvent != null, null, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
711
712         pDcImpl->__pRequestList = new (std::nothrow) LinkedList(SingleObjectDeleter);
713         SysTryReturn(NID_IO, pDcImpl->__pRequestList != null, null, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
714
715         pDcImpl->__pMapDataControlEvent = pMapDataControlEvent.release();
716
717         if (access == L"readonly")
718         {
719                 pDcImpl->__access = _DATACONTROL_ACCESS_READ;
720         }
721         else if (access == L"writeonly")
722         {
723                 pDcImpl->__access = _DATACONTROL_ACCESS_WRITE;
724         }
725         else if (access == L"readwrite")
726         {
727                 pDcImpl->__access = _DATACONTROL_ACCESS_READWRITE;
728         }
729         else
730         {
731                 pDcImpl->__access = _DATACONTROL_ACCESS_UNDEFINED;
732                 SysLog(NID_IO, "The accessibility of DataControl provider is invalid.");
733         }
734
735         return pDc.release();
736 }
737
738 }} // Tizen::App
739