Update for thread-safety of AppResource
[platform/framework/native/appfw.git] / src / app / FApp_AppResourceImpl.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_AppResourceImpl.cpp
19  * @brief       This is the implementation for the _AppResourceImpl class.
20  */
21
22 #include <unique_ptr.h>
23
24 #include <FBaseResult.h>
25 #include <FBaseSysLog.h>
26 #include <FBaseColHashMap.h>
27 #include <FBaseRt_LibraryImpl.h>
28
29 #include <FAppAppResource.h>
30 #include "FApp_AppManagerImpl.h"
31 #include "FApp_AppResourceString.h"
32 #include "FApp_IAppResourceBitmap.h"
33
34 #include "FApp_AppResourceImpl.h"
35
36
37 using namespace Tizen::Base;
38 using namespace Tizen::Base::Collection;
39 using namespace Tizen::Base::Runtime;
40 using namespace Tizen::Graphics;
41 using namespace Tizen::Io;
42
43
44 namespace Tizen { namespace App
45 {
46
47 #define BITMAP_PIXEL_FORMAT_INVALID (BITMAP_PIXEL_FORMAT_MIN)
48
49
50 static _IAppResourceBitmap*(* p_Create_IAppResourceBitmapInstanceN)(int type, const String& value) = null;
51
52 Tizen::Base::Collection::HashMap* _AppResourceImpl::__pContainer = null;
53 Tizen::Base::Runtime::Mutex* _AppResourceImpl::__pLock = null;
54
55 _AppResourceImpl::_AppResourceImpl(void)
56         : __p_AppResourceString(null)
57         , __p_IAppResourceBitmap(null)
58         , __type(APP_RESOURCE_DEFAULT)
59         , __value()
60 {
61 }
62
63 result
64 _AppResourceImpl::ReleaseInstance(const Tizen::Base::String& key)
65 {
66         result ret = E_SUCCESS;
67
68         if (__pContainer != null)
69         {
70                 result r = __pLock->Acquire();
71                 SysTryLog(NID_APP, !IsFailed(r), "Failed to acquire mutex.");
72
73                 AppResource* pAppResource = static_cast<AppResource*> (__pContainer->GetValue(key));
74                 delete pAppResource;
75
76                 ret = __pContainer->Remove(key);
77
78                 r = __pLock->Release();
79                 SysTryLog(NID_APP, !IsFailed(r), "Failed to release mutex.");
80         }
81
82         return ret;
83 }
84
85 // Exception: E_OUT_OF_MEMORY, E_SYSTEM, E_INVALID_ARG, E_OBJ_NOT_FOUND, E_APP_NOT_INSTALLED [Get_AppResourceStringN], Get_IAppResourceBitmapN
86 AppResource*
87 _AppResourceImpl::GetInstanceN(AppResourceBy type, const Tizen::Base::String& value)
88 {
89         result r = E_SUCCESS;
90         static pthread_once_t onceBlock = PTHREAD_ONCE_INIT;
91         if (__pContainer == null)
92         {
93                 ClearLastResult();
94                 pthread_once(&onceBlock, InitSingleton);
95                 r = GetLastResult();
96                 SysTryReturn(NID_APP, !IsFailed(r), null, E_SYSTEM, "[E_SYSTEM] Creating the container is failed [%s].", GetErrorMessage(r));
97         }
98
99         r = __pLock->Acquire();
100         SysTryLog(NID_APP, !IsFailed(r), "Failed to acquire mutex.");
101
102         bool hasAppResource = false;
103         r = __pContainer->ContainsKey(value, hasAppResource);
104         SysTryCatch(NID_APP, !IsFailed(r), r, r, "[%s] Checking to contain is failed.", GetErrorMessage(r));
105
106         if (hasAppResource)
107         {
108                 r = __pLock->Release();
109                 SysTryLog(NID_APP, !IsFailed(r), "Failed to release mutex.");
110
111                 return static_cast<AppResource*> (__pContainer->GetValue(value));
112         }
113         else
114         {
115                 std::unique_ptr< _AppResourceImpl > pAppResourceImpl(new (std::nothrow) _AppResourceImpl());
116                 SysTryCatch(NID_APP, pAppResourceImpl != null, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY,"[E_OUT_OF_MEMORY] Unable to allocate memory for AppResourceImpl.");
117
118                 std::unique_ptr< _AppResourceString > pAppResourceString(_AppResourceString::Get_AppResourceStringN(type, value));
119                 r = GetLastResult();
120                 SysTryCatch(NID_APP, !IsFailed(r), r, r, "[%s] Unable to get _AppResourceString.", GetErrorMessage(r));
121
122                 std::unique_ptr< _IAppResourceBitmap > pAppResourceBitmap(Get_IAppResourceBitmapN(type, value));
123                 r = GetLastResult();
124                 SysTryCatch(NID_APP, !IsFailed(r), r, r, "[%s] Unable to get _IAppResourceBitmap.", GetErrorMessage(r));
125
126                 pAppResourceImpl->__p_AppResourceString = pAppResourceString.release();
127                 pAppResourceImpl->__p_IAppResourceBitmap = pAppResourceBitmap.release();
128                 pAppResourceImpl->__type = type;
129                 pAppResourceImpl->__value = value;
130
131                 std::unique_ptr< String > pStr(new (std::nothrow) String(value));
132                 SysTryCatch(NID_APP, pStr != null, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Creating a key is failed.");
133
134                 AppResource* pAppResource = new (std::nothrow) AppResource;
135                 SysTryCatch(NID_APP, pAppResource != null, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Unable to allocate memory for AppResource");
136
137                 pAppResource->__pAppResourceImpl = pAppResourceImpl.release();
138                 r = __pContainer->Add(*pStr, *pAppResource);
139                 if (IsFailed(r))
140                 {
141                         delete pAppResource;
142                         SysTryCatch(NID_APP, false, r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] Adding an element to the container is failed.");
143                 }
144
145                 pStr.release();
146
147                 r = __pLock->Release();
148                 SysTryLog(NID_APP, !IsFailed(r), "Failed to release mutex.");
149
150                 return pAppResource;
151         }
152
153         // fall thru
154 CATCH:
155         SetLastResult(r);
156
157         r = __pLock->Release();
158         SysTryLog(NID_APP, !IsFailed(r), "Failed to release mutex.");
159
160         return null;
161 }
162
163 _IAppResourceBitmap*
164 _AppResourceImpl::Get_IAppResourceBitmapN(AppResourceBy type, const Tizen::Base::String& value)
165 {
166         if (p_Create_IAppResourceBitmapInstanceN == null)
167         {
168                 _LibraryImpl& lib = _AppManagerImpl::GetInstance()->GetUiLibraryImpl();
169                 p_Create_IAppResourceBitmapInstanceN =
170                                 reinterpret_cast<_IAppResourceBitmap*(*)(int, const String&)>(lib.GetProcAddress(L"_Create_IAppResourceBitmapInstanceN"));
171                 SysTryReturn(NID_APP, p_Create_IAppResourceBitmapInstanceN != null,
172                                 null, E_SYSTEM, "[E_SYSTEM] Failed to get Bitmap resource [%s].", GetErrorMessage(E_SYSTEM));
173         }
174
175         std::unique_ptr< _IAppResourceBitmap > pAppResourceBitmap(p_Create_IAppResourceBitmapInstanceN(type, value));
176         SysTryReturn(NID_APP, pAppResourceBitmap != null, null,
177                         E_SYSTEM, "[%s] Unable to get IAppResourceBitmap.", GetErrorMessage(E_SYSTEM));
178
179         return pAppResourceBitmap.release();
180 }
181
182 _AppResourceImpl::~_AppResourceImpl(void)
183 {
184         delete __p_AppResourceString;
185         delete __p_IAppResourceBitmap;
186 }
187
188 result
189 _AppResourceImpl::GetString(const String& resourceId, String& loadedString)
190 {
191         if (__p_AppResourceString == null)
192         {
193                 __p_AppResourceString = _AppResourceString::Get_AppResourceStringN(__type, __value);
194                 SysTryReturnResult(NID_APP, __p_AppResourceString == null, E_FAILURE, "Failed to get String resource.");
195         }
196
197         return __p_AppResourceString->GetString(resourceId, loadedString);
198 }
199
200 Bitmap*
201 _AppResourceImpl::GetBitmapN(const String& imgFilePath, BitmapPixelFormat pixelFormat)
202 {
203         if (__p_IAppResourceBitmap == null)
204         {
205                 __p_IAppResourceBitmap = Get_IAppResourceBitmapN(__type, __value);
206                 SysTryReturn(NID_APP, __p_IAppResourceBitmap == null,
207                                 null, E_SYSTEM, "[%s] Failed to get Bitmap resource.", GetErrorMessage(E_SYSTEM));
208         }
209
210         return __p_IAppResourceBitmap->GetBitmapN(imgFilePath, pixelFormat);
211 }
212
213 Bitmap*
214 _AppResourceImpl::GetBitmapN(const String& imgFilePath)
215 {
216         return GetBitmapN(imgFilePath, BITMAP_PIXEL_FORMAT_INVALID);
217 }
218
219 _AppResourceImpl*
220 _AppResourceImpl::GetInstance(void)
221 {
222         AppResource* pAppResource = AppResource::GetInstance();
223         if (pAppResource)
224         {
225                 return pAppResource->__pAppResourceImpl;
226         }
227         return null;
228 }
229
230 void
231 _AppResourceImpl::Reinitialize(void)
232 {
233         _AppResourceImpl* pThis = _AppResourceImpl::GetInstance();
234         if (pThis == null)
235         {
236                 SysLog(NID_APP, "No _AppResourceImpl instance.");
237                 return;
238         }
239
240         if (__pContainer != null)
241         {
242                 std::unique_ptr< IMapEnumerator > pMapEnum(__pContainer->GetMapEnumeratorN());
243                 if (pMapEnum)
244                 {
245                         while(pMapEnum->MoveNext() == E_SUCCESS)
246                         {
247                                 AppResource* pAppResource = static_cast<AppResource*> (pMapEnum->GetValue());
248                                 if (pAppResource && pAppResource->__pAppResourceImpl)
249                                 {
250                                         _AppResourceImpl* pAppResourceImpl = pAppResource->__pAppResourceImpl;
251                                         delete pAppResourceImpl->__p_AppResourceString;
252                                         pAppResourceImpl->__p_AppResourceString =
253                                                         _AppResourceString::Get_AppResourceStringN(pAppResourceImpl->__type, pAppResourceImpl->__value);
254
255                                         // This function will be called on Language change event
256                                         // Need not to re-initialize Bitmap resource as language change does not affect bitmap resource path
257                                 }
258                         }
259                 }
260         }
261 }
262
263 Bitmap*
264 _AppResourceImpl::GetNonScalingBitmapN(const Tizen::Base::String& imagePath)
265 {
266         _IAppResourceBitmap* pAppResourceBitmap = Tizen::App::_AppResourceImpl::Get_IAppResourceBitmapN(APP_RESOURCE_BITMAP);
267
268         if (pAppResourceBitmap != null)
269         {
270                 return pAppResourceBitmap->GetBitmapN(imagePath, BITMAP_PIXEL_FORMAT_INVALID, false);
271         }
272         else
273         {
274                 SysLog(NID_APP, "Getting pAppResourceBitmap instance is failed");
275                 return null;
276         }
277 }
278
279 void
280 _AppResourceImpl::InitSingleton(void)
281 {
282         std::unique_ptr< HashMap > pContainer(new (std::nothrow) HashMap(SingleObjectDeleter));
283         SysTryReturnVoidResult(NID_APP, pContainer != null, E_OUT_OF_MEMORY, "[%s] Creating the container is failed.");
284
285         result r = pContainer->Construct();
286         SysTryReturnVoidResult(NID_APP, !IsFailed(r), E_SYSTEM, "[E_SYSTEM] Constructing the container is failed.");
287
288         __pContainer = pContainer.release();
289
290         std::unique_ptr< Mutex > pLock(new (std::nothrow) Mutex());
291         SysTryReturnVoidResult(NID_APP, pLock != null, E_OUT_OF_MEMORY, "[%s] Creating the mutex is failed.");
292
293         r = pLock->Create();
294         SysTryReturnVoidResult(NID_APP, !IsFailed(r), E_SYSTEM, "[E_SYSTEM] Constructing the mutex is failed.");
295
296         __pLock = pLock.release();
297
298         std::atexit(DestroySingleton);
299 }
300
301 void
302 _AppResourceImpl::DestroySingleton(void)
303 {
304         delete __pContainer;
305         delete __pLock;
306 }
307
308 } } // Tizen::App