Increase SqlDataControl request buffer size
[platform/framework/native/appfw.git] / src / app / FApp_SqlDataControlImpl.cpp
1 //
2 // Open Service Platform
3 // Copyright (c) 2012 Samsung Electronics Co., Ltd.
4 //
5 // Licensed under the Apache License, Version 2.0 (the License);
6 // you may not use this file except in compliance with the License.
7 // You may obtain a copy of the License at
8 //
9 //     http://www.apache.org/licenses/LICENSE-2.0
10 //
11 // Unless required by applicable law or agreed to in writing, software
12 // distributed under the License is distributed on an "AS IS" BASIS,
13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 // See the License for the specific language governing permissions and
15 // limitations under the License.
16 //
17
18 /**
19  * @file        FApp_SqlDataControlImpl.cpp
20  * @brief       This is the implementation for the %_SqlDataControlImpl class.
21  */
22
23 #include <typeinfo>
24 #include <new>
25 #include <unique_ptr.h>
26
27 #include <appsvc/appsvc.h>
28
29 #include <FBaseInteger.h>
30 #include <FBaseString.h>
31 #include <FBaseLongLong.h>
32 #include <FBaseColIList.h>
33 #include <FBaseColIMap.h>
34 #include <FBaseColIMapEnumerator.h>
35 #include <FBaseRtIEventArg.h>
36 #include <FBaseSysLog.h>
37 #include <FIoFile.h>
38 #include <FAppApp.h>
39 #include <FAppSqlDataControl.h>
40 #include <FAppISqlDataControlResponseListener.h>
41
42 #include <FBase_StringConverter.h>
43 #include <FIo_DataControlResultSetEnumerator.h>
44
45 #include "FApp_AppControlManager.h"
46 #include "FApp_SqlDataControlImpl.h"
47 #include "FApp_AppArg.h"
48 #include "FApp_DataControlManager.h"
49
50 #define DATACONTROL_PROTOCOL_VER_2_1_0_2 // ver_2.1.0.2
51
52 using namespace std;
53
54 using namespace Tizen::Base;
55 using namespace Tizen::Base::Collection;
56 using namespace Tizen::Base::Runtime;
57 using namespace Tizen::App;
58 using namespace Tizen::Io;
59
60 namespace Tizen { namespace App
61 {
62
63 static const int MAX_REQUEST_COUNT = 128;
64 static const int _MAX_ARGUMENT_SIZE = 16384; // 16KB
65 static const int _MAX_REQUEST_ARGUMENT_SIZE = 1048576; // 1MB
66 static const char* _DATACONTROL_REQUEST_DIR = "/tmp/osp/DataControlRequest/\0";
67
68 class _SqlDataControlEventArg
69         : public IEventArg
70 {
71 public:
72                 _SqlDataControlEventArg(_DataControlRequestType requestType, RequestId reqId, String providerId, String dataId,
73                                 _DataControlResultSetEnumerator* pResultSetEnum, long long insertRowId, bool providerResult, String* pErrorMsg)
74                         : __requestType(requestType)
75                         , __reqId(reqId)
76                         , __providerId(providerId)
77                         , __dataId(dataId)
78                         , __pResultSetEnum(pResultSetEnum)
79                         , __insertRowId(insertRowId)
80                         , __providerResult(providerResult)
81                         , __pErrorMsg(pErrorMsg)
82                 {
83                 }
84                 ~_SqlDataControlEventArg(void)
85                 {
86                         delete __pResultSetEnum;
87                         delete __pErrorMsg;
88                 }
89
90                 _DataControlRequestType __requestType;
91                 RequestId __reqId;
92                 String __providerId;
93                 String __dataId;
94                 _DataControlResultSetEnumerator* __pResultSetEnum;
95                 long long __insertRowId;
96                 bool __providerResult;
97                 String* __pErrorMsg;
98 };
99
100 class _SqlDataControlEvent
101         : public Event
102 {
103 protected:
104                 virtual void FireImpl(IEventListener& listener, const IEventArg& arg);
105 };
106
107 void
108 _SqlDataControlEvent::FireImpl(IEventListener& listener, const IEventArg& arg)
109 {
110         const _SqlDataControlEventArg* pArg = dynamic_cast<const _SqlDataControlEventArg*>(&arg);
111         if (pArg != null)
112         {
113                 ISqlDataControlResponseListener* pListener = dynamic_cast<ISqlDataControlResponseListener*> (&listener);
114                 if (pListener != null)
115                 {
116                         switch (pArg->__requestType)
117                         {
118                         case _DATACONTROL_REQUEST_TYPE_SQL_QUERY:
119                                 pListener->OnSqlDataControlSelectResponseReceived(pArg->__reqId, pArg->__providerId, pArg->__dataId,
120                                                 *(pArg->__pResultSetEnum), pArg->__providerResult, pArg->__pErrorMsg);
121                                 break;
122                         case _DATACONTROL_REQUEST_TYPE_SQL_INSERT:
123                                 pListener->OnSqlDataControlInsertResponseReceived(pArg->__reqId, pArg->__providerId, pArg->__dataId,
124                                                  pArg->__insertRowId, pArg->__providerResult, pArg->__pErrorMsg);
125                                 break;
126                         case _DATACONTROL_REQUEST_TYPE_SQL_UPDATE:
127                                 pListener->OnSqlDataControlUpdateResponseReceived(pArg->__reqId, pArg->__providerId, pArg->__dataId,
128                                                 pArg->__providerResult, pArg->__pErrorMsg);
129                                 break;
130                         case _DATACONTROL_REQUEST_TYPE_SQL_DELETE:
131                                 pListener->OnSqlDataControlDeleteResponseReceived(pArg->__reqId, pArg->__providerId, pArg->__dataId,
132                                                 pArg->__providerResult, pArg->__pErrorMsg);
133                                 break;
134                         default:
135                                 break;
136                         }
137                 }
138         }
139 }
140
141 // private
142 _SqlDataControlImpl::_SqlDataControlImpl(void)
143         : __appId(L"")
144         , __providerId(L"")
145         , __access(_DATACONTROL_ACCESS_UNDEFINED)
146         , __pPreviousListener(null)
147         , __pSqlDataControlEvent(null)
148 {
149 }
150
151 _SqlDataControlImpl::~_SqlDataControlImpl(void)
152 {
153         delete __pSqlDataControlEvent;
154 }
155
156 _SqlDataControlImpl*
157 _SqlDataControlImpl::GetInstance(SqlDataControl& dc)
158 {
159         return dc.__pSqlDataControlImpl;
160 }
161
162 const _SqlDataControlImpl*
163 _SqlDataControlImpl::GetInstance(const SqlDataControl& dc)
164 {
165         return dc.__pSqlDataControlImpl;
166 }
167
168 result
169 _SqlDataControlImpl::StartSqlDataControl(int type, const IList* pDataList, int* pReq)
170 {
171         Integer* pReqId = null;
172         _DataControlRequestInfo* pReqInfo = null;
173         result r = E_SUCCESS;
174
175         int req = -1;
176         _AppControlManager* pAppManagerImpl = _AppControlManager::GetInstance();
177
178         // Check the request count of DataControl operation
179         int count = pAppManagerImpl->GetLaunchRequestCount();
180         SysLog(NID_APP, "Current launch request count: %d", count);
181
182         SysTryReturnResult(NID_APP, count < MAX_REQUEST_COUNT, E_MAX_EXCEEDED, "The number of requests has exceeded the maximum limit.");
183
184         _AppArg* pArg = new (std::nothrow) _AppArg;  // XXX: pArg will be released in _AppManagerImpl::LaunchApp().
185         SysTryReturnResult(NID_APP, pArg != null, E_OUT_OF_MEMORY, "insufficient memory");
186
187         pArg->Construct(*this, static_cast <_DataControlRequestType>(type), pDataList);
188
189         if (__pSqlDataControlEvent)
190         {
191                 // reqId is system-wide id because the bundle is system-wide.
192 #if 0
193                 _AppControlManager::_RequestGuard reqObj = _AppControlManager::_RequestGuard(*pAppManagerImpl, pArg, SqlDataControlCallback, __pSqlDataControlEvent, -1);
194                 req = reqObj.GetRequestNumber();
195 #else
196                 _DataControlManager* pDcMgr = _DataControlManager::GetInstance();
197                 _AppControlManager::_RequestGuard reqObj = _AppControlManager::_RequestGuard(*pAppManagerImpl, pArg, SqlDataControlCallback, pDcMgr, -1);
198                 req = reqObj.GetRequestNumber();
199 #endif
200                 pReqId = new (std::nothrow) Integer(req);
201                 SysTryCatch(NID_APP, pReqId != null, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY,
202                                 "[E_OUT_OF_MEMORY] The memory is insufficient");
203
204                 pReqInfo = new (std::nothrow) _DataControlRequestInfo(__pSqlDataControlEvent);
205                 SysTryCatch(NID_APP, pReqId != null, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY,
206                                 "[E_OUT_OF_MEMORY] The memory is insufficient");
207
208                 r = pDcMgr->AddRequestInfo(pReqId, pReqInfo);
209                 SysTryCatch(NID_APP, !IsFailed(r), r = E_SYSTEM, E_SYSTEM, "[%s] Failed to add request info", GetErrorMessage(r));
210
211                 r = pAppManagerImpl->LaunchApp(__appId, pArg, req);
212                 if (IsFailed(r))
213                 {
214                         SysPropagate(NID_APP, r);
215                         reqObj.Invalidate();
216                         pDcMgr->RemoveRequestInfo(*pReqId);
217                         delete pArg;
218                         return r;
219                 }
220
221                 if (pReq)
222                 {
223                         *pReq = req;
224                 }
225         }
226         else
227         {
228                 r = pAppManagerImpl->LaunchApp(__appId, pArg);
229                 SysTryCatch(NID_APP, !IsFailed(r), , r, "[%s] Propagating to caller...", GetErrorMessage(r));
230                 delete pArg;
231         }
232
233         return E_SUCCESS;
234
235 CATCH:
236         delete pArg;
237         delete pReqId;
238         delete pReqInfo;
239         return r;
240 }
241
242 result
243 _SqlDataControlImpl::Select(const String& dataId, const IList* pColumnList, const String* pWhere,
244                 const String *pOrder, RequestId& reqId, int pageNo, int countPerPage)
245 {
246         SysTryReturnResult(NID_APP, pageNo > 0, E_INVALID_ARG, "The specified pageNo parameter is less than 1");
247         SysTryReturnResult(NID_APP, countPerPage > 0, E_INVALID_ARG, "The specified countPerPage parameter is less than 1");
248         SysTryReturnResult(NID_APP, (__access & _DATACONTROL_ACCESS_READ) > 0, E_ILLEGAL_ACCESS,
249                         "The SELECT query is not permitted by DataControl provider.");
250
251         const String* pColumn = null;
252         int id = 0;
253         result r = E_SUCCESS;
254         SysLog(NID_APP, "[DC_CALLER_SEND] SqlDataControl SELECT");
255
256         ArrayList* pArgList = new ArrayList();
257         pArgList->Construct();
258
259         pArgList->Add(*(new String(dataId))); // list(0): data ID
260         long long argSize = dataId.GetLength() * sizeof(wchar_t);
261
262         if (pColumnList != null)
263         {
264                 int columnCount = pColumnList->GetCount();
265                 SysTryCatch(NID_APP, columnCount > 0, r = E_INVALID_ARG, E_INVALID_ARG,
266                                 "[E_INVALID_ARG] The specified pColumnList parameter is empty.");
267
268                 pArgList->Add(*(new String(Integer::ToString(columnCount)))); // list(1): selected column count
269                 SysLog(NID_APP, "[DC_CALLER_SEND] selected column count: %d", columnCount);
270
271                 int i = 0;
272                 while (i < columnCount) // list(2): column list
273                 {
274                         pColumn = dynamic_cast< const String* >(pColumnList->GetAt(i));
275                         SysTryCatch(NID_APP, pColumn != null, r = E_INVALID_ARG, E_INVALID_ARG,
276                                         "[E_INVALID_ARG] The object is not String class.");
277
278                         pArgList->Add(*(new String(*pColumn)));
279                         argSize += pColumn->GetLength() * sizeof(wchar_t);
280                         SysLog(NID_APP, "[DC_CALLER_SEND] column[%d]: %ls", i, pColumn->GetPointer());
281                         i++;
282                 }
283         }
284         else
285         {
286                 pArgList->Add(*(new String(L"NULL")));
287         }
288
289         if (pWhere != null)     // list(3): where clause
290         {
291                 pArgList->Add(*(new String(*pWhere)));
292                 argSize += pWhere->GetLength() * sizeof(wchar_t);
293                 SysLog(NID_APP, "[DC_CALLER_SEND] pWhere: %ls", pWhere->GetPointer());
294         }
295         else
296         {
297                 pArgList->Add(*(new String(L"NULL")));
298         }
299
300         if (pOrder != null)     // list(4): order clause
301         {
302                 pArgList->Add(*(new String(*pOrder)));
303                 argSize += pOrder->GetLength() * sizeof(wchar_t);
304                 SysLog(NID_APP, "[DC_CALLER_SEND] pOrder: %ls", pOrder->GetPointer());
305         }
306         else
307         {
308                 pArgList->Add(*(new String(L"NULL")));
309         }
310         SysTryCatch(NID_APP, argSize <= _MAX_ARGUMENT_SIZE, r = E_MAX_EXCEEDED, E_MAX_EXCEEDED,
311                         "[E_MAX_EXCEEDED] The size of sending argument (%d) exceeds the maximum limit.", argSize);
312
313         pArgList->Add(*(new String(Integer::ToString(pageNo)))); // list(5): page number
314
315         pArgList->Add(*(new String(Integer::ToString(countPerPage)))); // list(6): count per page
316
317         r = StartSqlDataControl(_DATACONTROL_REQUEST_TYPE_SQL_QUERY, pArgList, &id);
318         SysTryCatch(NID_APP, !IsFailed(r), , r, "[%s] Propagating to caller...", GetErrorMessage(r));
319
320         reqId = static_cast< RequestId >(id);
321
322         SysLog(NID_APP, "[DC_CALLER_SEND] data: %ls, pColumnList: 0x%x, pWhere: 0x%x, pOrder: 0x%x, req: %d, pageNo: %d, countPerPage: %d",
323                         dataId.GetPointer(), pColumnList, pWhere, pOrder, reqId, pageNo, countPerPage);
324
325         // fall through
326 CATCH:
327         pArgList->RemoveAll(true);
328         delete pArgList;
329
330         return r;
331 }
332
333 result
334 _SqlDataControlImpl::SqlDataControlCallback(void* data, _AppArg* pArg, _AppArg* pResArg, service_result_e res, int prop, int option)
335 {
336         ArrayList* pResultList = null;
337         String* pResult = null;
338         String* pProviderId = null;
339         String* pDataId = null;
340         String* pErrorMessage = null;
341         String* pErrorMsg = null;
342         String* pTmpPath = null;
343         String* pInsertRowId = null;
344         _DataControlResultSetEnumerator* pResultSetEnum = null;
345         int requestType = 0;
346         int reqId = 0;
347         int launchReqId = 0;
348         int providerRes = 0;
349         bool providerResult = true;
350         //bundle* origBundle = null;
351         bundle* resBundle = null;
352         _SqlDataControlEventArg* pEventArg = null;
353         const char* p = null;
354         result r = E_SUCCESS;
355
356         SysTryReturnResult(NID_APP, pResArg != null, E_INVALID_ARG, "Empty result callback.");
357         SysLog(NID_APP, "appsvc result value: %d", res);
358
359         resBundle = pResArg->GetBundle();
360         if (resBundle)
361         {
362                 p = appsvc_get_data(resBundle, OSP_K_REQUEST_ID);
363                 SysTryCatch(NID_APP, p, r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] invalid bundle");
364                 reqId = atoi(p);
365                 Integer key(reqId);
366
367                 _DataControlManager* pDcMgr = static_cast< _DataControlManager* >(data);
368                 _DataControlRequestInfo* pReqInfo = pDcMgr->GetRequestInfo(key);
369                 SysTryCatch(NID_APP, pReqInfo != null, r = E_SYSTEM, E_SYSTEM,
370                                 "[E_SYSTEM] Failed to get request info");
371
372                 _SqlDataControlEvent* pSqlDataControlEvent = dynamic_cast< _SqlDataControlEvent* >(pReqInfo->GetEvent());
373                 SysTryCatch(NID_APP, pSqlDataControlEvent != null, r = E_SYSTEM, E_SYSTEM,
374                                 "[E_SYSTEM] invalid request info");
375
376                 pDcMgr->RemoveRequestInfo(key);
377
378                 if (pSqlDataControlEvent != null && typeid(pSqlDataControlEvent) == typeid(_SqlDataControlEvent*))
379                 {
380                         // result list
381                         pResultList = _AppArg::GetListN(resBundle, OSP_K_ARG);
382                         SysTryCatch(NID_APP, pResultList, r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] invalid result");
383
384                         pResult = dynamic_cast <String*>(pResultList->GetAt(0)); // result list[0]
385                         SysTryCatch(NID_APP, pResult, r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] invalid result");
386                         Integer::Parse(*pResult, providerRes);
387                         providerResult = static_cast< bool >(providerRes);
388
389                         pErrorMessage = dynamic_cast< String* >(pResultList->GetAt(1)); // result list[1]
390                         SysTryCatch(NID_APP, pErrorMessage, r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] invalid result");
391                         pErrorMsg = new (std::nothrow) String(*pErrorMessage);
392                         SysTryCatch(NID_APP, pErrorMsg, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY,
393                                         "[E_OUT_OF_MEMORY] The memory is insufficient.");
394
395                         // request info
396                         //origBundle = pArg->GetBundle();
397
398                         p = appsvc_get_data(resBundle, OSP_K_DATACONTROL_REQUEST_TYPE);
399                         SysTryCatch(NID_APP, p, r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] invalid bundle");
400                         requestType = atoi(p);
401
402                         p = appsvc_get_data(resBundle, OSP_K_DATACONTROL_PROVIDER);
403                         SysTryCatch(NID_APP, p, r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] invalid bundle");
404                         pProviderId = new (std::nothrow) String(p);
405                         SysTryCatch(NID_APP, pProviderId, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY,
406                                         "[E_OUT_OF_MEMORY] The memory is insufficient.");
407
408                         p = appsvc_get_data(resBundle, OSP_K_DATACONTROL_DATA);
409                         SysTryCatch(NID_APP, p, r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] invalid bundle");
410                         pDataId = new (std::nothrow) String(p);
411                         SysTryCatch(NID_APP, pDataId, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY,
412                                         "[E_OUT_OF_MEMORY] The memory is insufficient.");
413
414                         SysLog(NID_APP, "[DC_CALLER_RECV] provider result: %ld, requestType: %d, req: %d, provider: %ls, data: %ls, errorMsg: %ls ",
415                                         providerRes, requestType, reqId, pProviderId->GetPointer(), pDataId->GetPointer(), pErrorMsg->GetPointer());
416
417                         switch (static_cast <_DataControlRequestType>(requestType))
418                         {
419                         case _DATACONTROL_REQUEST_TYPE_SQL_QUERY:
420                         {
421                                 pResultSetEnum = new (std::nothrow) _DataControlResultSetEnumerator;
422                                 SysTryCatch(NID_APP, pResultSetEnum, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY,
423                                                 "[E_OUT_OF_MEMORY] The memory is insufficient.");
424
425                                 if (providerResult == true)
426                                 {
427                                         pTmpPath = dynamic_cast< String* >(pResultList->GetAt(2)); // result list[2]
428                                         if (pTmpPath == null)
429                                         {
430                                                 SysLogException(NID_APP, E_SYSTEM, "[E_SYSTEM] invalid result");
431                                                 delete pResultSetEnum;
432                                                 goto CATCH;
433                                         }
434
435                                         SysLog(NID_APP, "[DC_CALLER_RECV] tempPath: %ls", pTmpPath->GetPointer());
436                                         if (pTmpPath->Equals(L"NoResultSet", true) == false) // Result set exists
437                                         {
438                                                 pResultSetEnum->SetPath(*pTmpPath);
439                                         }
440                                 }
441
442                                 pEventArg = new (std::nothrow) _SqlDataControlEventArg(_DATACONTROL_REQUEST_TYPE_SQL_QUERY, static_cast <RequestId>(reqId),
443                                                 *pProviderId, *pDataId, pResultSetEnum, -1, providerResult, pErrorMsg);
444                                 SysTryCatch(NID_APP, pEventArg != null, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
445                                 pSqlDataControlEvent->Fire(*pEventArg);
446
447                                 if (pTmpPath)
448                                 {
449                                         r = File::Remove(*pTmpPath); // Remove temporary file after releasing _ResultSetEnumerator.
450                                         SysTryLog(NID_APP, !IsFailed(r), "Failed to remove temp file for result set: %ls", pTmpPath->GetPointer());
451                                 }
452
453                                 break;
454                         }
455                         case _DATACONTROL_REQUEST_TYPE_SQL_INSERT:
456                         {
457                                 long long insertRowId = -1;
458                                 if (providerResult == true)
459                                 {
460                                         pInsertRowId = dynamic_cast< String* >(pResultList->GetAt(2)); // result list[2]
461                                         SysTryCatch(NID_APP, pInsertRowId, r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] invalid result");
462
463                                         LongLong::Parse(*pInsertRowId, insertRowId);
464                                 }
465
466                                 pEventArg = new (std::nothrow) _SqlDataControlEventArg(_DATACONTROL_REQUEST_TYPE_SQL_INSERT, static_cast <RequestId>(reqId),
467                                                 *pProviderId, *pDataId, null, insertRowId, providerResult, pErrorMsg);
468                                 SysTryCatch(NID_APP, pEventArg != null, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
469                                 pSqlDataControlEvent->Fire(*pEventArg);
470                                 break;
471                         }
472                         case _DATACONTROL_REQUEST_TYPE_SQL_UPDATE:
473                         {
474                                 pEventArg = new (std::nothrow) _SqlDataControlEventArg(_DATACONTROL_REQUEST_TYPE_SQL_UPDATE, static_cast <RequestId>(reqId),
475                                                 *pProviderId, *pDataId, null, -1, providerResult, pErrorMsg);
476                                 SysTryCatch(NID_APP, pEventArg != null, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
477                                 pSqlDataControlEvent->Fire(*pEventArg);
478                                 break;
479                         }
480                         case _DATACONTROL_REQUEST_TYPE_SQL_DELETE:
481                         {
482                                 pEventArg = new (std::nothrow) _SqlDataControlEventArg(_DATACONTROL_REQUEST_TYPE_SQL_DELETE, static_cast <RequestId>(reqId),
483                                                 *pProviderId, *pDataId, null, -1, providerResult, pErrorMsg);
484                                 SysTryCatch(NID_APP, pEventArg != null, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
485                                 pSqlDataControlEvent->Fire(*pEventArg);
486                                 break;
487                         }
488                         default:
489                                 break;
490                         }
491
492                         pResultList->RemoveAll(true);
493                         delete pResultList;
494                         delete pProviderId;
495                 }
496         }
497
498         p = appsvc_get_data(pArg->GetBundle(), OSP_K_REQUEST_ID);
499         SysTryCatch(NID_APP, p, r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] invalid bundle");
500         launchReqId = atoi(p);
501
502         // Remove the request count
503         SysLog(NID_APP, "Remove a launch request: req: %d", launchReqId);
504         _AppControlManager::GetInstance()->RemoveLaunchRequest(launchReqId);
505
506         return E_SUCCESS;
507
508 CATCH:
509         if (pResultList)
510         {
511                 pResultList->RemoveAll(true);
512                 delete pResultList;
513         }
514         delete pProviderId;
515
516         return r;
517 }
518
519 result
520 _SqlDataControlImpl::Insert(const String& dataId, const IMap& insertMap, RequestId& reqId)
521 {
522         SysTryReturnResult(NID_APP, (__access & _DATACONTROL_ACCESS_WRITE) > 0, E_ILLEGAL_ACCESS,
523                         "The INSERT query is not permitted by DataControl provider.");
524
525         int columnCount = 0;
526         int id = 0;
527         int i = 0;
528         int uniqueId = -1;
529         File request;
530         IMapEnumerator* pMapEnum = null;
531         result r = E_SUCCESS;
532         SysLog(NID_APP, "[DC_CALLER_SEND] SqlDataControl INSERT");
533
534         columnCount = insertMap.GetCount();
535         SysTryReturnResult(NID_APP, columnCount > 0, E_INVALID_ARG, "The specified insertMap parameter is empty.");
536
537         ArrayList* pArgList = new (std::nothrow) ArrayList();
538         pArgList->Construct();
539
540         pArgList->Add(new (std::nothrow) String(dataId)); // list[0]: data ID
541         long long argSize = dataId.GetLength() * sizeof(wchar_t);
542
543         pArgList->Add(new (std::nothrow) String(Integer::ToString(columnCount))); // list[1]: inserted column count
544         SysLog(NID_APP, "[DC_CALLER_SEND] inserted column count: %d", columnCount);
545
546 #ifdef DATACONTROL_PROTOCOL_VER_2_1_0_2
547         String tmpPath(_DATACONTROL_REQUEST_DIR);
548         tmpPath.Append(App::GetInstance()->GetAppId());
549
550         _DataControlManager* pDcMgr = _DataControlManager::GetInstance();
551         SysTryCatch(NID_APP, pDcMgr, r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] Failed to get _DataControlManager instance.");
552         uniqueId = pDcMgr->GetUniqueId();
553
554         tmpPath.Append(uniqueId);
555         SysLog(NID_APP, "[DC_CALLER_SEND] request: %ls", tmpPath.GetPointer());
556
557         r = request.Construct(tmpPath, L"w+", true);
558         SysTryCatch(NID_APP, !IsFailed(r), r = E_SYSTEM, E_SYSTEM, "[%s] Failed to create request (%ls).",
559                         GetErrorMessage(r), tmpPath.GetPointer());
560
561         pArgList->Add(new (std::nothrow) String(tmpPath)); // list[2]: path 
562 #endif
563
564         pMapEnum = const_cast< IMap* >(&insertMap)->GetMapEnumeratorN();
565         while (pMapEnum->MoveNext() == E_SUCCESS) // list: column-value pairs
566         {
567 #ifdef DATACONTROL_PROTOCOL_VER_2_1_0_2
568                 int length = 0;
569                 String* pColumn = null;
570                 String* pValue = null;
571                 unique_ptr< char[] > pData(null);
572
573                 pColumn = dynamic_cast< String* >(pMapEnum->GetKey());
574                 SysTryCatch(NID_APP, pColumn != null, r = E_INVALID_ARG, E_INVALID_ARG,
575                                 "[E_INVALID_ARG] The object is not String class.");
576
577                 pData.reset(_StringConverter::CopyToCharArrayN(*pColumn));
578                 SysTryCatch(NID_APP, pData != null, r = GetLastResult(), GetLastResult(), "[%s] Invalid request value",
579                                 GetErrorMessage(GetLastResult()));
580
581                 length = strlen(pData.get());
582                 r = request.Write(&length, sizeof(int)); // data length
583                 SysTryCatch(NID_APP, !IsFailed(r), , E_SYSTEM, "[%s] Failed to send request.", GetErrorMessage(r));
584
585                 r = request.Write(pData.get(), length); // data
586                 SysTryCatch(NID_APP, !IsFailed(r), , E_SYSTEM, "[%s] Failed to send request.", GetErrorMessage(r));
587
588                 pValue = dynamic_cast< String* >(pMapEnum->GetValue());
589                 SysTryCatch(NID_APP, pValue != null, r = E_INVALID_ARG, E_INVALID_ARG,
590                                 "[E_INVALID_ARG] The object is not String class.");
591
592                 pData.reset(_StringConverter::CopyToCharArrayN(*pValue));
593                 SysTryCatch(NID_APP, pData != null, r = GetLastResult(), GetLastResult(), "[%s] Invalid request value",
594                                 GetErrorMessage(GetLastResult()));
595
596                 length = strlen(pData.get());
597                 r = request.Write(&length, sizeof(int)); // data length
598                 SysTryCatch(NID_APP, !IsFailed(r), , E_SYSTEM, "[%s] Failed to send request.", GetErrorMessage(r));
599
600                 r = request.Write(pData.get(), length); // data
601                 SysTryCatch(NID_APP, !IsFailed(r), , E_SYSTEM, "[%s] Failed to send request.", GetErrorMessage(r));
602
603                 argSize += pColumn->GetLength() * sizeof(wchar_t);
604                 argSize += pValue->GetLength() * sizeof(wchar_t);
605 #else
606                 String* pColumn = dynamic_cast< String* >(pMapEnum->GetKey());
607                 SysTryCatch(NID_APP, pColumn != null, r = E_INVALID_ARG, E_INVALID_ARG,
608                                 "[E_INVALID_ARG] The object is not String class.");
609
610                 pArgList->Add(*(new String(*pColumn)));
611                 SysLog(NID_APP, "[DC_CALLER_SEND] pColumn[%d]: %ls", i, pColumn->GetPointer());
612
613                 String* pValue = dynamic_cast< String* >(pMapEnum->GetValue());
614                 SysTryCatch(NID_APP, pValue != null, r = E_INVALID_ARG, E_INVALID_ARG,
615                                 "[E_INVALID_ARG] The object is not String class.");
616
617                 pArgList->Add(*(new String(*pValue)));
618                 SysLog(NID_APP, "[DC_CALLER_SEND] pValue[%d]: %ls", i, pValue->GetPointer());
619
620                 argSize += pColumn->GetLength() * sizeof(wchar_t);
621                 argSize += pValue->GetLength() * sizeof(wchar_t);
622                 i++;
623 #endif
624         }
625         SysTryCatch(NID_APP, argSize <= _MAX_REQUEST_ARGUMENT_SIZE, r = E_MAX_EXCEEDED, E_MAX_EXCEEDED,
626                         "[E_MAX_EXCEEDED] The size of sending argument (%d) exceeds the maximum limit.", argSize);
627
628 #ifdef DATACONTROL_PROTOCOL_VER_2_1_0_2
629         request.Flush();
630 #endif
631
632         r = StartSqlDataControl(_DATACONTROL_REQUEST_TYPE_SQL_INSERT, pArgList, &id);
633         SysTryCatch(NID_APP, !IsFailed(r), , r, "[%s] Propagating to caller...", GetErrorMessage(r));
634
635         reqId = static_cast< RequestId >(id);
636
637         SysLog(NID_APP, "[DC_CALLER_SEND] data: %ls, insertMap: 0x%x, req: %d", dataId.GetPointer(), &insertMap, reqId);
638
639         // fall through
640 CATCH:
641         pArgList->RemoveAll(true);
642         delete pArgList;
643         delete pMapEnum;
644
645         return r;
646 }
647
648 result
649 _SqlDataControlImpl::Update(const String& dataId, const IMap& updateMap, const String* pWhere, RequestId& reqId)
650 {
651         SysTryReturnResult(NID_APP, (__access & _DATACONTROL_ACCESS_WRITE) > 0, E_ILLEGAL_ACCESS,
652                         "The UPDATE query is not permitted by DataControl provider.");
653
654         int columnCount = 0;
655         int id = 0;
656         int i = 0;
657         int uniqueId = -1;
658         File request;
659         IMapEnumerator* pMapEnum = null;
660         result r = E_SUCCESS;
661         SysLog(NID_APP, "[DC_CALLER_SEND] SqlDataControl UPDATE");
662
663         columnCount = updateMap.GetCount();
664         SysTryReturnResult(NID_APP, columnCount > 0, E_INVALID_ARG, "The specified insertMap parameter is empty.");
665
666         ArrayList* pArgList = new ArrayList();
667         pArgList->Construct();
668
669         pArgList->Add(new (std::nothrow) String(dataId)); // list[0]: data ID
670         long long argSize = dataId.GetLength() * sizeof(wchar_t);
671
672         pArgList->Add(new (std::nothrow) String(Integer::ToString(columnCount))); // list[1]: updated column count
673         SysLog(NID_APP, "[DC_CALLER_SEND] updated column count: %d", columnCount);
674
675 #ifdef DATACONTROL_PROTOCOL_VER_2_1_0_2
676         String tmpPath(_DATACONTROL_REQUEST_DIR);
677         tmpPath.Append(App::GetInstance()->GetAppId());
678
679         _DataControlManager* pDcMgr = _DataControlManager::GetInstance();
680         SysTryCatch(NID_APP, pDcMgr, r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] Failed to get _DataControlManager instance.");
681         uniqueId = pDcMgr->GetUniqueId();
682
683         tmpPath.Append(uniqueId);
684         SysLog(NID_APP, "[DC_CALLER_SEND] request: %ls", tmpPath.GetPointer());
685
686         r = request.Construct(tmpPath, L"w+", true);
687         SysTryCatch(NID_APP, !IsFailed(r), r = E_SYSTEM, E_SYSTEM, "[%s] Failed to create request (%ls).",
688                         GetErrorMessage(r), tmpPath.GetPointer());
689
690         pArgList->Add(new (std::nothrow) String(tmpPath)); // list[2]: path 
691 #endif
692
693         pMapEnum = const_cast< IMap* >(&updateMap)->GetMapEnumeratorN();
694         while (pMapEnum->MoveNext() == E_SUCCESS) // list: column-value pairs
695         {
696 #ifdef DATACONTROL_PROTOCOL_VER_2_1_0_2
697                 int length = 0;
698                 String* pColumn = null;
699                 String* pValue = null;
700                 unique_ptr< char[] > pData(null);
701
702                 pColumn = dynamic_cast< String* >(pMapEnum->GetKey());
703                 SysTryCatch(NID_APP, pColumn != null, r = E_INVALID_ARG, E_INVALID_ARG,
704                                 "[E_INVALID_ARG] The object is not String class.");
705
706                 pData.reset(_StringConverter::CopyToCharArrayN(*pColumn));
707                 SysTryCatch(NID_APP, pData != null, r = GetLastResult(), GetLastResult(), "[%s] Invalid request value",
708                                 GetErrorMessage(GetLastResult()));
709
710                 length = strlen(pData.get());
711                 r = request.Write(&length, sizeof(int)); // data length
712                 SysTryCatch(NID_APP, !IsFailed(r), , E_SYSTEM, "[%s] Failed to send request.", GetErrorMessage(r));
713
714                 r = request.Write(pData.get(), length); // data
715                 SysTryCatch(NID_APP, !IsFailed(r), , E_SYSTEM, "[%s] Failed to send request.", GetErrorMessage(r));
716
717                 pValue = dynamic_cast< String* >(pMapEnum->GetValue());
718                 SysTryCatch(NID_APP, pValue != null, r = E_INVALID_ARG, E_INVALID_ARG,
719                                 "[E_INVALID_ARG] The object is not String class.");
720
721                 pData.reset(_StringConverter::CopyToCharArrayN(*pValue));
722                 SysTryCatch(NID_APP, pData != null, r = GetLastResult(), GetLastResult(), "[%s] Invalid request value",
723                                 GetErrorMessage(GetLastResult()));
724
725                 length = strlen(pData.get());
726                 r = request.Write(&length, sizeof(int)); // data length
727                 SysTryCatch(NID_APP, !IsFailed(r), , E_SYSTEM, "[%s] Failed to send request.", GetErrorMessage(r));
728
729                 r = request.Write(pData.get(), length); // data
730                 SysTryCatch(NID_APP, !IsFailed(r), , E_SYSTEM, "[%s] Failed to send request.", GetErrorMessage(r));
731
732                 argSize += pColumn->GetLength() * sizeof(wchar_t);
733                 argSize += pValue->GetLength() * sizeof(wchar_t);
734 #else
735                 String* pColumn = dynamic_cast< String* >(pMapEnum->GetKey());
736                 SysTryCatch(NID_APP, pColumn != null, r = E_INVALID_ARG, E_INVALID_ARG,
737                                 "[E_INVALID_ARG] The object is not String class.");
738
739                 pArgList->Add(*(new String(*pColumn)));
740                 SysLog(NID_APP, "[DC_CALLER_SEND] pColumn[%d]: %ls", i, pColumn->GetPointer());
741
742                 String* pValue = dynamic_cast< String* >(pMapEnum->GetValue());
743                 SysTryCatch(NID_APP, pValue != null, r = E_INVALID_ARG, E_INVALID_ARG,
744                                 "[E_INVALID_ARG] The object is not String class.");
745
746                 pArgList->Add(*(new String(*pValue)));
747                 SysLog(NID_APP, "[DC_CALLER_SEND] pValue[%d]: %ls", i, pValue->GetPointer());
748
749                 argSize += pColumn->GetLength() * sizeof(wchar_t);
750                 argSize += pValue->GetLength() * sizeof(wchar_t);
751                 i++;
752 #endif
753         }
754
755 #ifdef DATACONTROL_PROTOCOL_VER_2_1_0_2
756         request.Flush();
757 #endif
758
759         if (pWhere != null)     // list: where clause
760         {
761                 pArgList->Add(new (std::nothrow) String(*pWhere));
762                 argSize += pWhere->GetLength() * sizeof(wchar_t);
763                 SysLog(NID_APP, "[DC_CALLER_SEND] pWhere: %ls", pWhere->GetPointer());
764         }
765         else
766         {
767                 pArgList->Add(new (std::nothrow) String(L"NULL"));
768         }
769         SysTryCatch(NID_APP, argSize <= _MAX_REQUEST_ARGUMENT_SIZE, r = E_MAX_EXCEEDED, E_MAX_EXCEEDED,
770                         "[E_MAX_EXCEEDED] The size of sending argument (%d) exceeds the maximum limit.", argSize);
771
772         r = StartSqlDataControl(_DATACONTROL_REQUEST_TYPE_SQL_UPDATE, pArgList, &id);
773         SysTryCatch(NID_APP, !IsFailed(r), , r, "[%s] Propagating to caller...", GetErrorMessage(r));
774
775         reqId = static_cast< RequestId >(id);
776
777         SysLog(NID_APP, "[DC_CALLER_SEND] data: %ls, updateMap: 0x%x, pWhere: 0x%x, req: %d",
778                                 dataId.GetPointer(), &updateMap, pWhere, reqId);
779
780         // fall through
781 CATCH:
782         pArgList->RemoveAll(true);
783         delete pArgList;
784         delete pMapEnum;
785
786         return r;
787 }
788
789 result
790 _SqlDataControlImpl::Delete(const String& dataId, const String* pWhere, RequestId& reqId)
791 {
792         SysTryReturnResult(NID_APP, (__access & _DATACONTROL_ACCESS_WRITE) > 0, E_ILLEGAL_ACCESS,
793                         "The DELETE query is not permitted by DataControl provider.");
794
795         int id = 0;
796         result r = E_SUCCESS;
797         SysLog(NID_APP, "[DC_CALLER_SEND] SqlDataControl DELETE");
798
799         ArrayList* pArgList = new ArrayList();
800         pArgList->Construct();
801
802         pArgList->Add(*(new String(dataId))); // list(0): data ID
803         long long argSize = dataId.GetLength() * sizeof(wchar_t);
804
805         if (pWhere != null)     // list(1): where clause
806         {
807                 pArgList->Add(*(new String(*pWhere)));
808                 argSize += pWhere->GetLength() * sizeof(wchar_t);
809                 SysLog(NID_APP, "[DC_CALLER_SEND] pWhere: %ls", pWhere->GetPointer());
810         }
811         else
812         {
813                 pArgList->Add(*(new String(L"NULL")));
814         }
815         SysTryCatch(NID_APP, argSize <= _MAX_ARGUMENT_SIZE, r = E_MAX_EXCEEDED, E_MAX_EXCEEDED,
816                         "[E_MAX_EXCEEDED] The size of sending argument (%d) exceeds the maximum limit.", argSize);
817
818         r = StartSqlDataControl(_DATACONTROL_REQUEST_TYPE_SQL_DELETE, pArgList, &id);
819         SysTryCatch(NID_APP, !IsFailed(r), , r, "[%s] Propagating to caller...", GetErrorMessage(r));
820
821         reqId = static_cast< RequestId >(id);
822
823         SysLog(NID_APP, "[DC_CALLER_SEND] data: %ls, pWhere: 0x%x, req: %d", dataId.GetPointer(), pWhere, reqId);
824
825         // fall through
826 CATCH:
827         pArgList->RemoveAll(true);
828         delete pArgList;
829
830         return r;
831 }
832
833 result
834 _SqlDataControlImpl::SetSqlDataControlResponseListener(ISqlDataControlResponseListener* pListener)
835 {
836         result r = E_SUCCESS;
837
838         if (__pPreviousListener != null)
839         {
840                 r =  __pSqlDataControlEvent->RemoveListener(*__pPreviousListener);
841                 SysTryReturnResult(NID_APP, !IsFailed(r), E_SYSTEM, "Remove listener failed.");
842                  __pPreviousListener = null;
843         }
844
845         if (pListener != null)
846         {
847                 r =  __pSqlDataControlEvent->AddListener(*pListener);
848                 if (IsFailed(r))
849                 {
850                         switch (r)
851                         {
852                         case E_OBJ_ALREADY_EXIST:
853                                 return E_SUCCESS;
854                         case E_INVALID_OPERATION:
855                                 SysLogException(NID_APP, E_SYSTEM, "[E_SYSTEM] The thread setting the listener is worker thread.");
856                                 return E_SYSTEM;
857                         default:
858                                 SysLogException(NID_APP, r, "[%s] Propagating to caller...", GetErrorMessage(r));
859                                 return r;
860                         }
861                 }
862         }
863
864         __pPreviousListener = pListener;
865
866         return E_SUCCESS;
867 }
868
869 // private
870 SqlDataControl*
871 _SqlDataControlImpl::CreateSqlDataControl(const String& appId, const String& providerId, const String& access)
872 {
873         unique_ptr<SqlDataControl> pDc(new (std::nothrow) SqlDataControl);
874         SysTryReturn(NID_APP, pDc != null, null, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient");
875
876         _SqlDataControlImpl* pDcImpl = _SqlDataControlImpl::GetInstance(*pDc);
877         pDcImpl->__appId = appId;
878         pDcImpl->__providerId = providerId;
879         unique_ptr<_SqlDataControlEvent> pSqlDataControlEvent(new (std::nothrow) _SqlDataControlEvent);
880         SysTryReturn(NID_IO, pSqlDataControlEvent != null, null, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
881
882         pDcImpl->__pSqlDataControlEvent = pSqlDataControlEvent.release();
883
884         if (access == L"readonly")
885         {
886                 pDcImpl->__access = _DATACONTROL_ACCESS_READ;
887         }
888         else if (access == L"writeonly")
889         {
890                 pDcImpl->__access = _DATACONTROL_ACCESS_WRITE;
891         }
892         else if (access == L"readwrite")
893         {
894                 pDcImpl->__access = _DATACONTROL_ACCESS_READWRITE;
895         }
896         else
897         {
898                 pDcImpl->__access = _DATACONTROL_ACCESS_UNDEFINED;
899                 SysLog(NID_IO, "The accessibility of DataControl provider is invalid.");
900         }
901
902         return pDc.release();
903 }
904
905 }} // Tizen::App
906