Beta merge 2
[profile/ivi/wrt-plugins-tizen.git] / src / standards / Tizen / Application / JSApplication.cpp
1 /*
2  * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
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 #include <memory>
19 #include <CommonsJavaScript/Converter.h>
20 #include <CommonsJavaScript/Validator.h>
21 #include <CommonsJavaScript/JSUtils.h>
22 #include <CommonsJavaScript/JSCallbackManager.h>
23 #include <CommonsJavaScript/Utils.h>
24 #include <Tizen/Common/SecurityExceptions.h>
25 #include <Commons/Exception.h>
26 #include <Tizen/Common/JSTizenExceptionFactory.h>
27 #include <Tizen/Common/JSTizenException.h>
28 #include <API/Application/ApplicationFactory.h>
29 #include <API/Application/EventListInstalledApplications.h>
30 #include <API/Application/EventManageApplication.h>
31 #include <API/Application/EventGetApplication.h>
32 #include <API/Application/EventLaunchService.h>
33 #include "plugin_config.h"
34 #include "ApplicationAnswerReceiver.h"
35 #include "ApplicationListener.h"
36 #include "JSApplication.h"
37 #include "ApplicationConverter.h"
38 #include "ApplicationServiceReplyCallback.h"
39 #include "ApplicationInformationEventCallback.h"
40 #include "LaunchServicePrivateData.h"
41 #include "ApplicationInformationEventPrivateData.h"
42 #include "JSApplicationService.h"
43 #include <bundle.h>
44
45 namespace TizenApis {
46 namespace Tizen1_0 {
47 namespace Application {
48
49 using namespace std;
50 using namespace DPL;
51 using namespace TizenApis::Api::Application;
52 using namespace TizenApis::Commons;
53
54 using namespace WrtDeviceApis;
55 using namespace WrtDeviceApis::Commons;
56 using namespace WrtDeviceApis::CommonsJavaScript;
57
58 JSClassRef JSApplication::m_jsClassRef = NULL;
59
60 JSClassDefinition JSApplication::m_classInfo = {
61                 0,
62                 kJSClassAttributeNone,
63                 "application",
64                 NULL,
65                 NULL,
66                 m_function,
67                 initialize,
68                 finalize,
69                 NULL, //hasProperty,
70                 NULL, //getProperty,
71                 NULL, //setProperty,
72                 NULL, //deleteProperty,Geolocation
73                 NULL, //getPropertyNames,
74                 NULL,
75                 NULL,
76                 hasInstance,
77                 NULL
78 };
79
80 JSStaticFunction JSApplication::m_function[] = {
81                 { "launch",JSApplication::launch,kJSPropertyAttributeNone },
82                 { "exit",JSApplication::exit,kJSPropertyAttributeNone },
83                 { "kill",JSApplication::kill,kJSPropertyAttributeNone },
84                 { "hide",JSApplication::hide,kJSPropertyAttributeNone },
85                 { "getApplicationInformations",JSApplication::getApplicationInformations,kJSPropertyAttributeNone },
86                 { "getRunningApplicationContexts",JSApplication::getRunningApplicationContexts,kJSPropertyAttributeNone },
87                 { "getApplicationInformation",JSApplication::getApplicationInformation,kJSPropertyAttributeNone },
88                 { "getCurrentApplicationContext",JSApplication::getCurrentApplicationContext,kJSPropertyAttributeNone },
89                 { "addApplicationInformationEventListener",JSApplication::addApplicationInformationEventListener,kJSPropertyAttributeNone },
90                 { "removeApplicationInformationEventListener",JSApplication::removeApplicationInformationEventListener,kJSPropertyAttributeNone },
91                 { "launchService",JSApplication::launchService,kJSPropertyAttributeNone },
92                 { "getApplicationService",JSApplication::getApplicationService,kJSPropertyAttributeNone },
93                 { 0, 0, 0 }
94 };
95
96 const JSClassRef JSApplication::getClassRef() {
97         if (!m_jsClassRef) {
98                 m_jsClassRef = JSClassCreate(&m_classInfo);
99         }
100         return m_jsClassRef;
101 }
102
103 const JSClassDefinition* JSApplication::getClassInfo() {
104         return &m_classInfo;
105 }
106
107 void JSApplication::initialize(JSContextRef context, JSObjectRef object) {
108         JSApplicationPriv* priv = static_cast<JSApplicationPriv*>(JSObjectGetPrivate(object));
109         assert(!priv && "Invalid object creation.");
110         IApplicationPtr applications(ApplicationFactory::getInstance().createApplication());
111         priv = new JSApplicationPriv(context, applications);
112         if (!JSObjectSetPrivate(object, static_cast<void*>(priv))) {
113                 LogError("Object can't store private data.");
114                 delete priv;
115         }
116 }
117
118 void JSApplication::finalize(JSObjectRef object) {
119         JSApplicationPriv* priv = static_cast<JSApplicationPriv*> (JSObjectGetPrivate(object));
120         JSObjectSetPrivate(object, NULL);
121         delete priv;
122 }
123
124 bool JSApplication::hasInstance(JSContextRef context, 
125         JSObjectRef constructor, 
126         JSValueRef possibleInstance, 
127         JSValueRef* exception) 
128 {
129         return JSValueIsObjectOfClass(context, possibleInstance, getClassRef());
130 }
131
132 JSValueRef JSApplication::launch(JSContextRef context, 
133         JSObjectRef object, 
134         JSObjectRef thisObject, 
135         size_t argumentCount,
136         const JSValueRef arguments[], 
137         JSValueRef* exception) 
138 {
139         JSApplicationPriv *priv = static_cast<JSApplicationPriv*> (JSObjectGetPrivate(thisObject));
140         assert(priv && "Invalid private pointer.");
141         JSContextRef gContext = priv->getContext();
142
143         AceSecurityStatus status = APPLICATION_CHECK_ACCESS(
144                                 gContext,
145                                 APPLICATION_FUNCTION_API_LAUNCH);
146         TIZEN_SYNC_ACCESS_HANDLER(status, context, exception);
147
148         ApplicationConverterFactory::ConverterType converter = ApplicationConverterFactory::getConverter(context);
149
150     if ((argumentCount < 2) ||
151         (JSValueIsNull(context, arguments[0]) ||
152          JSValueIsUndefined(context, arguments[0]) ||
153          JSObjectIsFunction(context, converter->toJSObjectRef(arguments[0]))) ||
154         (JSValueIsNull(context, arguments[1]) || 
155          JSValueIsUndefined(context, arguments[1]) ||
156          !JSObjectIsFunction(context, converter->toJSObjectRef(arguments[1]))) ||
157         (argumentCount > 2 &&
158          (JSValueIsUndefined(context, arguments[2]) ||
159          !JSObjectIsFunction(context, converter->toJSObjectRef(arguments[2])))) ||
160         (argumentCount > 3 &&
161          (JSValueIsUndefined(context, arguments[3]) ||
162          JSObjectIsFunction(context, converter->toJSObjectRef(arguments[3]))))) {
163         LogError("Wrong callbacks parameters");
164                 return JSTizenExceptionFactory::postException(context, exception,JSTizenException::TYPE_MISMATCH_ERROR, "Type mistmatch error");
165     }
166
167         JSCallbackManagerPtr callbackManager = JSCallbackManager::createObject(gContext);
168         callbackManager->setOnSuccess(arguments[1]);
169         if (argumentCount > 2)
170                 callbackManager->setOnError(arguments[2]);
171
172         EventManageApplicationPtr event(new EventManageApplication());
173         Try{
174                 IApplicationPtr applications(priv->getObject());
175                 event->setEventType(EventManageApplication::APP_MANAGER_LAUNCH_APPLICATION);
176                 event->setAppId(converter->toString( arguments[0] ));
177                 if (argumentCount > 3) {
178                         event->setArgument(converter->toString(arguments[3]));
179                 }
180                 event->setPrivateData(StaticPointerCast<IEventPrivateData>(callbackManager));
181                 event->setForAsynchronousCall(new ApplicationAnswerReceiver(callbackManager));
182                 applications->launch(event);
183         }Catch (WrtDeviceApis::Commons::ConversionException){
184                 return JSTizenExceptionFactory::postException(context, exception,JSTizenException::TYPE_MISMATCH_ERROR, "Type mistmatch error");
185         }Catch (WrtDeviceApis::Commons::PendingOperationException){
186                 callbackManager->callOnError(JSTizenExceptionFactory::makeErrorObject(context,JSTizenException::INVALID_VALUES_ERROR,"Pending operation failed"));
187                 return JSValueMakeUndefined(context);
188         }Catch (WrtDeviceApis::Commons::InvalidArgumentException){
189                 callbackManager->callOnError(JSTizenExceptionFactory::makeErrorObject(context,JSTizenException::INVALID_VALUES_ERROR,"Invalid value error"));
190                 return JSValueMakeUndefined(context);
191         }Catch (WrtDeviceApis::Commons::NullPointerException){
192                 callbackManager->callOnError(JSTizenExceptionFactory::makeErrorObject(context,JSTizenException::UNKNOWN_ERROR,"Unknown error"));
193                 return JSValueMakeUndefined(context);
194         }Catch(WrtDeviceApis::Commons::Exception){
195                 LogError("Exception: " << _rethrown_exception.GetMessage() << " Code: " << _rethrown_exception.getCode());
196                 return JSTizenExceptionFactory::postException(context, exception,JSTizenException::UNKNOWN_ERROR, "Unknown error");
197         }
198         return JSValueMakeUndefined(context);
199 }
200
201 JSValueRef JSApplication::kill(JSContextRef context, 
202         JSObjectRef object, 
203         JSObjectRef thisObject, 
204         size_t argumentCount,
205         const JSValueRef arguments[], 
206         JSValueRef* exception) 
207 {
208         JSApplicationPriv *priv = static_cast<JSApplicationPriv*> (JSObjectGetPrivate(thisObject));
209         assert(priv && "Invalid private pointer.");
210         JSContextRef gContext = priv->getContext();
211
212         AceSecurityStatus status = APPLICATION_CHECK_ACCESS(
213                                 gContext,
214                                 APPLICATION_FUNCTION_API_KILL);
215         TIZEN_SYNC_ACCESS_HANDLER(status, context, exception);
216
217         ApplicationConverterFactory::ConverterType converter = ApplicationConverterFactory::getConverter(context);
218
219     if ((argumentCount < 2) ||
220         (JSValueIsNull(context,
221                         arguments[0]) ||
222          JSValueIsUndefined(context,
223                              arguments[0]) ||
224          !JSObjectIsFunction(context,
225                              converter->toJSObjectRef(arguments[0]))) ||
226         (JSValueIsNull(context,
227                         arguments[1]) ||
228          JSValueIsUndefined(context,
229                              arguments[1]) ||
230          !JSObjectIsFunction(context,
231                              converter->toJSObjectRef(arguments[1]))) ||                             
232         (argumentCount > 2 &&
233          !JSValueIsNull(context,
234                         arguments[2]) &&
235          !JSValueIsUndefined(context,
236                              arguments[2]) &&
237          !JSObjectIsFunction(context,
238                              converter->toJSObjectRef(arguments[2])))) {
239         LogError("Wrong callbacks parameters");
240                 return JSTizenExceptionFactory::postException(context, exception,JSTizenException::TYPE_MISMATCH_ERROR, "Type mistmatch error");
241     }
242
243         JSCallbackManagerPtr callbackManager = JSCallbackManager::createObject(gContext);
244         callbackManager->setOnSuccess(arguments[1]);
245         if (argumentCount > 2)
246                 callbackManager->setOnError(arguments[2]);
247
248         EventManageApplicationPtr event(new EventManageApplication());
249         Try{
250                 ApplicationContextPtr appContext = converter->toApplicationContext(arguments[0]);
251                 
252                 IApplicationPtr applications(priv->getObject());
253                 event->setEventType(EventManageApplication::APP_MANAGER_KILL_APPLICATION);
254                 event->setApplicationContext(appContext);
255                 event->setPrivateData(StaticPointerCast<IEventPrivateData>(callbackManager));
256                 event->setForAsynchronousCall(new ApplicationAnswerReceiver(callbackManager));
257                 applications->kill(event);
258         }Catch (WrtDeviceApis::Commons::ConversionException){
259                 return JSTizenExceptionFactory::postException(context, exception,JSTizenException::TYPE_MISMATCH_ERROR, "Type mistmatch error");
260         }Catch (WrtDeviceApis::Commons::PendingOperationException){
261                 callbackManager->callOnError(JSTizenExceptionFactory::makeErrorObject(context,JSTizenException::INVALID_VALUES_ERROR,"Pending operation failed"));
262                 return JSValueMakeUndefined(context);
263         }Catch (WrtDeviceApis::Commons::InvalidArgumentException){
264                 callbackManager->callOnError(JSTizenExceptionFactory::makeErrorObject(context,JSTizenException::INVALID_VALUES_ERROR,"Invalid value error"));
265                 return JSValueMakeUndefined(context);
266         }Catch (WrtDeviceApis::Commons::NullPointerException){
267                 callbackManager->callOnError(JSTizenExceptionFactory::makeErrorObject(context,JSTizenException::UNKNOWN_ERROR,"Unknown error"));
268                 return JSValueMakeUndefined(context);
269         }Catch(WrtDeviceApis::Commons::Exception){
270                 LogError("Exception: " << _rethrown_exception.GetMessage() << " Code: " << _rethrown_exception.getCode());
271                 return JSTizenExceptionFactory::postException(context, exception,JSTizenException::UNKNOWN_ERROR, "Unknown error");
272         }
273         return JSValueMakeUndefined(context);
274 }
275
276 JSValueRef JSApplication::exit(JSContextRef context, 
277         JSObjectRef object, 
278         JSObjectRef thisObject, 
279         size_t argumentCount,
280         const JSValueRef arguments[], 
281         JSValueRef* exception) 
282 {
283         LogError("== [WS] enter JSApplication::exit");
284
285         JSApplicationPriv *priv = static_cast<JSApplicationPriv*> (JSObjectGetPrivate(thisObject));
286         assert(priv && "Invalid private pointer.");
287         JSContextRef gContext = priv->getContext();
288
289         LogError("== [WS] call ACE");
290         AceSecurityStatus status = APPLICATION_CHECK_ACCESS(
291                                 gContext,
292                                 APPLICATION_FUNCTION_API_EXIT);
293         TIZEN_SYNC_ACCESS_HANDLER(status, context, exception);
294
295         Try{
296                 LogError("== [WS] get applications");
297                 IApplicationPtr applications(priv->getObject());
298                 LogError("== [WS] applications->exit()");
299                 applications->exit();
300         } Catch(WrtDeviceApis::Commons::Exception){
301                 LogError("Exception: " << _rethrown_exception.GetMessage() << " Code: " << _rethrown_exception.getCode());
302                 return JSTizenExceptionFactory::postException(context, exception,JSTizenException::UNKNOWN_ERROR, "Unknown error");
303         }
304         LogError("exit JSApplication::exit");
305         return JSValueMakeUndefined(context);
306 }
307
308
309 JSValueRef JSApplication::hide(JSContextRef context, 
310         JSObjectRef object, 
311         JSObjectRef thisObject, 
312         size_t argumentCount,
313         const JSValueRef arguments[], 
314         JSValueRef* exception) 
315 {
316         JSApplicationPriv *priv = static_cast<JSApplicationPriv*> (JSObjectGetPrivate(thisObject));
317         assert(priv && "Invalid private pointer.");
318         JSContextRef gContext = priv->getContext();
319
320         AceSecurityStatus status = APPLICATION_CHECK_ACCESS(
321                                 gContext,
322                                 APPLICATION_FUNCTION_API_HIDE);
323         TIZEN_SYNC_ACCESS_HANDLER(status, context, exception);
324
325         ApplicationConverterFactory::ConverterType converter = ApplicationConverterFactory::getConverter(context);
326
327     if ((argumentCount < 2) ||
328         (JSValueIsNull(context,
329                         arguments[0]) ||
330          JSValueIsUndefined(context,
331                              arguments[0]) ||
332          !JSObjectIsFunction(context,
333                              converter->toJSObjectRef(arguments[0]))) ||
334         (JSValueIsNull(context,
335                         arguments[1]) ||
336          JSValueIsUndefined(context,
337                              arguments[1]) ||
338          !JSObjectIsFunction(context,
339                              converter->toJSObjectRef(arguments[1]))) ||                             
340         (argumentCount > 2 &&
341          !JSValueIsNull(context,
342                         arguments[2]) &&
343          !JSValueIsUndefined(context,
344                              arguments[2]) &&
345          !JSObjectIsFunction(context,
346                              converter->toJSObjectRef(arguments[2])))) {
347         LogError("Wrong callbacks parameters");
348                 return JSTizenExceptionFactory::postException(context, exception,JSTizenException::TYPE_MISMATCH_ERROR, "Type mistmatch error");
349     }
350
351         JSCallbackManagerPtr callbackManager = JSCallbackManager::createObject(gContext);
352         callbackManager->setOnSuccess(arguments[1]);
353         if (argumentCount > 2)
354                 callbackManager->setOnError(arguments[2]);
355
356         EventManageApplicationPtr event(new EventManageApplication());
357         Try{
358                 ApplicationContextPtr appContext = converter->toApplicationContext(arguments[0]);
359                 
360                 IApplicationPtr applications(priv->getObject());
361                 event->setEventType(EventManageApplication::APP_MANAGER_HIDE_APPLICATION);
362                 event->setApplicationContext(appContext);
363                 event->setPrivateData(StaticPointerCast<IEventPrivateData>(callbackManager));
364                 event->setForAsynchronousCall(new ApplicationAnswerReceiver(callbackManager));
365                 applications->hide(event);
366         }Catch (WrtDeviceApis::Commons::ConversionException){
367                 return JSTizenExceptionFactory::postException(context, exception,JSTizenException::TYPE_MISMATCH_ERROR, "Type mistmatch error");
368         }Catch (WrtDeviceApis::Commons::PendingOperationException){
369                 callbackManager->callOnError(JSTizenExceptionFactory::makeErrorObject(context,JSTizenException::INVALID_VALUES_ERROR,"Pending operation failed"));
370                 return JSValueMakeUndefined(context);
371         }Catch (WrtDeviceApis::Commons::InvalidArgumentException){
372                 callbackManager->callOnError(JSTizenExceptionFactory::makeErrorObject(context,JSTizenException::INVALID_VALUES_ERROR,"Invalid value error"));
373                 return JSValueMakeUndefined(context);
374         }Catch (WrtDeviceApis::Commons::NullPointerException){
375                 callbackManager->callOnError(JSTizenExceptionFactory::makeErrorObject(context,JSTizenException::UNKNOWN_ERROR,"Unknown error"));
376                 return JSValueMakeUndefined(context);
377         }Catch(WrtDeviceApis::Commons::Exception){
378                 LogError("Exception: " << _rethrown_exception.GetMessage() << " Code: " << _rethrown_exception.getCode());
379                 return JSTizenExceptionFactory::postException(context, exception,JSTizenException::UNKNOWN_ERROR, "Unknown error");
380         }
381         return JSValueMakeUndefined(context);
382 }
383
384
385 JSValueRef JSApplication::getApplicationInformations(JSContextRef context, 
386         JSObjectRef object, 
387         JSObjectRef thisObject, 
388         size_t argumentCount,
389         const JSValueRef arguments[], 
390         JSValueRef* exception) 
391 {
392         JSApplicationPriv *priv = static_cast<JSApplicationPriv*> (JSObjectGetPrivate(thisObject));
393         assert(priv && "Invalid private pointer.");
394         JSContextRef gContext = priv->getContext();
395
396         AceSecurityStatus status = APPLICATION_CHECK_ACCESS(
397                                 gContext,
398                                 APPLICATION_FUNCTION_API_GET_APPLICATION_INFORMATIONS);
399         TIZEN_SYNC_ACCESS_HANDLER(status, context, exception);
400
401         ApplicationConverterFactory::ConverterType converter = ApplicationConverterFactory::getConverter(context);
402
403     if ((argumentCount == 0) ||
404         (JSValueIsNull(context,
405                         arguments[0]) ||
406          JSValueIsUndefined(context,
407                              arguments[0]) ||
408          !JSObjectIsFunction(context,
409                              converter->toJSObjectRef(arguments[0]))) ||
410         (argumentCount > 1 &&
411          !JSValueIsNull(context,
412                         arguments[1]) &&
413          !JSValueIsUndefined(context,
414                              arguments[1]) &&
415          !JSObjectIsFunction(context,
416                              converter->toJSObjectRef(arguments[1])))) {
417         LogError("Wrong callbacks parameters");
418                 return JSTizenExceptionFactory::postException(context, exception,JSTizenException::TYPE_MISMATCH_ERROR, "Type mistmatch error");
419     }
420
421         JSCallbackManagerPtr callbackManager = JSCallbackManager::createObject(gContext);
422         callbackManager->setOnSuccess(arguments[0]);
423         if (argumentCount > 1)
424                 callbackManager->setOnError(arguments[1]);
425
426         EventListInstalledApplicationsPtr event(new EventListInstalledApplications());
427         Try{
428                 IApplicationPtr applications(priv->getObject());
429                 event->setEventType(EventListInstalledApplications::APPMANAGER_LIST_INSTALLED_APPLICATIONS);
430                 event->setPrivateData(StaticPointerCast<IEventPrivateData>(callbackManager));
431                 event->setForAsynchronousCall(new ApplicationAnswerReceiver(callbackManager));
432                 applications->listApplications(event);
433         }Catch (WrtDeviceApis::Commons::ConversionException){
434                 return JSTizenExceptionFactory::postException(context, exception,JSTizenException::TYPE_MISMATCH_ERROR, "Type mistmatch error");
435         }Catch (WrtDeviceApis::Commons::PendingOperationException){
436                 callbackManager->callOnError(JSTizenExceptionFactory::makeErrorObject(context,JSTizenException::INVALID_VALUES_ERROR,"Pending operation failed"));
437                 return JSValueMakeUndefined(context);
438         }Catch (WrtDeviceApis::Commons::InvalidArgumentException){
439                 callbackManager->callOnError(JSTizenExceptionFactory::makeErrorObject(context,JSTizenException::INVALID_VALUES_ERROR,"Invalid value error"));
440                 return JSValueMakeUndefined(context);
441         }Catch (WrtDeviceApis::Commons::NullPointerException){
442                 callbackManager->callOnError(JSTizenExceptionFactory::makeErrorObject(context,JSTizenException::UNKNOWN_ERROR,"Unknown error"));
443                 return JSValueMakeUndefined(context);
444         }Catch(WrtDeviceApis::Commons::Exception){
445                 LogError("Exception: " << _rethrown_exception.GetMessage() << " Code: " << _rethrown_exception.getCode());
446                 return JSTizenExceptionFactory::postException(context, exception,JSTizenException::UNKNOWN_ERROR, "Unknown error");
447         }
448         return JSValueMakeUndefined(context);
449 }
450
451 JSValueRef JSApplication::getApplicationInformation(JSContextRef context, 
452         JSObjectRef object, 
453         JSObjectRef thisObject, 
454         size_t argumentCount,
455         const JSValueRef arguments[], 
456         JSValueRef* exception) 
457 {
458         JSApplicationPriv *priv = static_cast<JSApplicationPriv*> (JSObjectGetPrivate(thisObject));
459
460         assert(priv && "Invalid private pointer.");
461         AceSecurityStatus status = APPLICATION_CHECK_ACCESS(
462                 priv->getContext(),
463                 APPLICATION_FUNCTION_API_GET_APPLICATION_INFORMATION);
464         TIZEN_SYNC_ACCESS_HANDLER(status, context, exception);
465         ApplicationConverterFactory::ConverterType converter = ApplicationConverterFactory::getConverter(context);
466
467
468         std::string appid;
469         
470         if ((argumentCount == 0) || ((argumentCount == 1) && JSValueIsNull(context, arguments[0]))) {
471                 // skip. return empty string 
472         } else if ((argumentCount == 1) && JSValueIsString(context, arguments[0])) {
473                 appid = converter->toString( arguments[0] );
474         } else if (JSValueIsUndefined(context, arguments[0])) {
475                 LogError("Wrong package " << JSValueIsNull(context, arguments[0]) <<", "<<JSValueIsUndefined(context, arguments[0]));
476                 return JSTizenExceptionFactory::postException(context, exception,JSTizenException::TYPE_MISMATCH_ERROR, "Type mistmatch error");
477         }
478         
479         Try
480     {
481                 IApplicationPtr applications(priv->getObject());
482                 EventGetApplicationPtr event(new EventGetApplication());
483                 event->setEventType(EventGetApplication::APP_MANAGER_GET_INFORMATION);
484                 event->setForSynchronousCall();
485                 event->setAppId(appid);
486                 applications->getApplication(event);
487                 if (event->getExceptionCode() == WrtDeviceApis::Commons::ExceptionCodes::NotFoundException) {
488                         return JSTizenExceptionFactory::postException(context, exception,JSTizenException::NOT_FOUND_ERROR, "Given package is not found");                      
489                 }
490                 return converter->toJSValueRef(event->getApplicationInformation());
491         }Catch (WrtDeviceApis::Commons::ConversionException){
492                 return JSTizenExceptionFactory::postException(context, exception,JSTizenException::TYPE_MISMATCH_ERROR, "Type mistmatch error");
493         }Catch (WrtDeviceApis::Commons::InvalidArgumentException){
494                 return JSTizenExceptionFactory::postException(context, exception,JSTizenException::INVALID_VALUES_ERROR,"Invalid value error");
495         }Catch (WrtDeviceApis::Commons::NullPointerException){
496                 return JSTizenExceptionFactory::postException(context, exception,JSTizenException::UNKNOWN_ERROR, "Unknown error");
497         }Catch(WrtDeviceApis::Commons::Exception){
498                 LogError("Exception: " << _rethrown_exception.GetMessage() << " Code: " << _rethrown_exception.getCode());
499                 return JSTizenExceptionFactory::postException(context, exception,JSTizenException::UNKNOWN_ERROR, "Unknown error");
500         }
501 }
502
503 JSValueRef JSApplication::getRunningApplicationContexts(JSContextRef context, 
504         JSObjectRef object, 
505         JSObjectRef thisObject, 
506         size_t argumentCount,
507         const JSValueRef arguments[], 
508         JSValueRef* exception) 
509 {
510         JSApplicationPriv *priv = static_cast<JSApplicationPriv*> (JSObjectGetPrivate(thisObject));
511
512         assert(priv && "Invalid private pointer.");
513         JSContextRef gContext = priv->getContext();
514
515         AceSecurityStatus status = APPLICATION_CHECK_ACCESS(
516                                 gContext,
517                                 APPLICATION_FUNCTION_API_GET_RUNNING_APPLICATION_CONTEXTS);
518         TIZEN_SYNC_ACCESS_HANDLER(status, context, exception);
519
520         ApplicationConverterFactory::ConverterType converter = ApplicationConverterFactory::getConverter(context);
521
522     if ((argumentCount == 0) ||
523         (JSValueIsNull(context,
524                         arguments[0]) ||
525          JSValueIsUndefined(context,
526                              arguments[0]) ||
527          !JSObjectIsFunction(context,
528                              converter->toJSObjectRef(arguments[0]))) ||
529         (argumentCount > 1 &&
530          !JSValueIsNull(context,
531                         arguments[1]) &&
532          !JSValueIsUndefined(context,
533                              arguments[1]) &&
534          !JSObjectIsFunction(context,
535                              converter->toJSObjectRef(arguments[1])))) {
536         LogError("Wrong callbacks parameters");
537                 return JSTizenExceptionFactory::postException(context, exception,JSTizenException::TYPE_MISMATCH_ERROR, "Type mistmatch error");
538     }
539
540         JSCallbackManagerPtr callbackManager = JSCallbackManager::createObject(gContext);
541         callbackManager->setOnSuccess(arguments[0]);
542         if (argumentCount > 1)
543                 callbackManager->setOnError(arguments[1]);
544
545         EventListInstalledApplicationsPtr event(new EventListInstalledApplications());
546         Try{
547                 IApplicationPtr applications(priv->getObject());
548                 event->setEventType(EventListInstalledApplications::APPMANAGER_LIST_RUNNING_APPLICATIONS);
549                 event->setPrivateData(StaticPointerCast<IEventPrivateData>(callbackManager));
550                 event->setForAsynchronousCall(new ApplicationAnswerReceiver(callbackManager));          
551                 applications->listApplications(event);
552         }Catch (WrtDeviceApis::Commons::ConversionException){
553                 return JSTizenExceptionFactory::postException(context, exception,JSTizenException::TYPE_MISMATCH_ERROR, "Type mistmatch error");
554         }Catch (WrtDeviceApis::Commons::PendingOperationException){
555                 callbackManager->callOnError(JSTizenExceptionFactory::makeErrorObject(context,JSTizenException::INVALID_VALUES_ERROR,"Pending operation failed"));
556                 return JSValueMakeUndefined(context);
557         }Catch (WrtDeviceApis::Commons::InvalidArgumentException){
558                 callbackManager->callOnError(JSTizenExceptionFactory::makeErrorObject(context,JSTizenException::INVALID_VALUES_ERROR,"Invalid value error"));
559                 return JSValueMakeUndefined(context);
560         }Catch (WrtDeviceApis::Commons::NullPointerException){
561                 callbackManager->callOnError(JSTizenExceptionFactory::makeErrorObject(context,JSTizenException::UNKNOWN_ERROR,"Unknown error"));
562                 return JSValueMakeUndefined(context);   
563         }Catch(WrtDeviceApis::Commons::Exception){
564                 LogError("Exception: " << _rethrown_exception.GetMessage() << " Code: " << _rethrown_exception.getCode());
565                 return JSTizenExceptionFactory::postException(context, exception,JSTizenException::UNKNOWN_ERROR, "Unknown error");
566         }
567         return JSValueMakeUndefined(context);
568 }
569
570 JSValueRef JSApplication::getCurrentApplicationContext(JSContextRef context, 
571         JSObjectRef object, 
572         JSObjectRef thisObject, 
573         size_t argumentCount,
574         const JSValueRef arguments[], 
575         JSValueRef* exception) 
576 {
577         JSApplicationPriv *priv = static_cast<JSApplicationPriv*> (JSObjectGetPrivate(thisObject));
578
579         assert(priv && "Invalid private pointer.");
580         AceSecurityStatus status = APPLICATION_CHECK_ACCESS(
581                 priv->getContext(),
582                 APPLICATION_FUNCTION_API_GET_CURRENT_APPLICATION_CONTEXT);
583         TIZEN_SYNC_ACCESS_HANDLER(status, context, exception);
584         ApplicationConverterFactory::ConverterType converter = ApplicationConverterFactory::getConverter(context);
585
586 #if 0
587         if(JSValueIsNull(context, arguments[0]) || JSValueIsUndefined(context, arguments[0])){
588                 LogError("Wrong package " << JSValueIsNull(context, arguments[0]) <<", "<<JSValueIsUndefined(context, arguments[0]));
589                 return JSTizenExceptionFactory::postException(context, exception,JSTizenException::TYPE_MISMATCH_ERROR, "Type mistmatch error");
590         }
591 #endif
592
593         EventGetApplicationPtr event(new EventGetApplication());
594
595         Try
596     {
597                 IApplicationPtr applications(priv->getObject());
598                 event->setEventType(EventGetApplication::APP_MANAGER_GET_CONTEXT);
599                 event->setForSynchronousCall();
600                 applications->getApplication(event);
601                 if (event->getExceptionCode() == WrtDeviceApis::Commons::ExceptionCodes::NotFoundException) {
602                         return JSTizenExceptionFactory::postException(context, exception,JSTizenException::NOT_FOUND_ERROR, "Given package is not found");                      
603                 } else if (event->getExceptionCode() == WrtDeviceApis::Commons::ExceptionCodes::UnknownException) {
604                         return JSTizenExceptionFactory::postException(context, exception,JSTizenException::UNKNOWN_ERROR, "Unknown error");
605                 }
606                 return converter->toJSValueRef(event->getApplicationContext());
607         }Catch (WrtDeviceApis::Commons::ConversionException){
608                 LogError("== [WS] error on type mismatch");
609                 return JSTizenExceptionFactory::postException(context, exception,JSTizenException::TYPE_MISMATCH_ERROR, "Type mistmatch error");
610         }Catch (WrtDeviceApis::Commons::InvalidArgumentException){
611                 return JSTizenExceptionFactory::postException(context, exception,JSTizenException::INVALID_VALUES_ERROR,"Invalid value error");
612         }Catch (WrtDeviceApis::Commons::NullPointerException){
613                 return JSTizenExceptionFactory::postException(context, exception,JSTizenException::UNKNOWN_ERROR, "Unknown error");
614         }Catch(WrtDeviceApis::Commons::Exception){
615                 LogError("Exception: " << _rethrown_exception.GetMessage() << " Code: " << _rethrown_exception.getCode());
616                 return JSTizenExceptionFactory::postException(context, exception,JSTizenException::UNKNOWN_ERROR, "Unknown error");
617         }
618 }
619
620 JSValueRef JSApplication::addApplicationInformationEventListener(JSContextRef context, 
621         JSObjectRef object, 
622         JSObjectRef thisObject, 
623         size_t argumentCount,
624         const JSValueRef arguments[], 
625         JSValueRef* exception) 
626 {
627         JSApplicationPriv *priv = static_cast<JSApplicationPriv*> (JSObjectGetPrivate(thisObject));
628
629         assert(priv && "Invalid private pointer.");
630         AceSecurityStatus status = APPLICATION_CHECK_ACCESS(
631                 priv->getContext(),
632                 APPLICATION_FUNCTION_API_ADD_APPLICATION_INFORMATION_EVENT_LISTENER);   
633         TIZEN_SYNC_ACCESS_HANDLER(status, context, exception);
634         ApplicationConverterFactory::ConverterType converter = ApplicationConverterFactory::getConverter(context);
635
636     if ((argumentCount == 0) ||
637         (JSValueIsNull(context,
638                         arguments[0]) ||
639          JSValueIsUndefined(context,
640                              arguments[0]) ||
641          JSObjectIsFunction(context,
642                              converter->toJSObjectRef(arguments[0]))) ||
643         (argumentCount > 1 &&
644          !JSValueIsNull(context,
645                         arguments[1]) &&
646          !JSValueIsUndefined(context,
647                              arguments[1]) &&
648          !JSObjectIsFunction(context,
649                              converter->toJSObjectRef(arguments[1])))) {
650         LogError("Wrong callbacks parameters");
651                 return JSTizenExceptionFactory::postException(context, exception,JSTizenException::TYPE_MISMATCH_ERROR, "Type mistmatch error");
652     }
653
654         JSObjectRef objectCallbacks = converter->toJSObjectRef(arguments[0]);
655
656         ApplicationInformationEventCallback result;
657     result.onInstalled = JSUtils::getJSPropertyOrUndefined(context, objectCallbacks, "onInstalled");
658     result.onUpdated = JSUtils::getJSPropertyOrUndefined(context, objectCallbacks, "onUpdated");
659     result.onUninstalled = JSUtils::getJSPropertyOrUndefined(context, objectCallbacks, "onUninstalled");
660
661         if (argumentCount == 2) {
662                 result.onError = arguments[1];
663         } else {
664                 result.onError =JSValueMakeUndefined(context);
665         }
666
667         Validator validator(context);
668         if ((!validator.isNullOrUndefined(result.onInstalled) && !validator.isCallback(result.onInstalled)) ||
669                 (!validator.isNullOrUndefined(result.onUpdated) && !validator.isCallback(result.onUpdated)) ||
670                 (!validator.isNullOrUndefined(result.onUninstalled) && !validator.isCallback(result.onUninstalled))) 
671         {
672                 LogError("Application Information Event Callbakc is not set properly!");
673                 Throw(InvalidArgumentException);
674         }
675
676         JSCallbackManagerPtr onInstalledCbm = JSCallbackManager::createObject(priv->getContext(), result.onInstalled, result.onError);
677         JSCallbackManagerPtr onUpdatedCbm   = JSCallbackManager::createObject(priv->getContext(), result.onUpdated, result.onError);
678         JSCallbackManagerPtr onUninstalledCbm = JSCallbackManager::createObject(priv->getContext(), result.onUninstalled, result.onError);
679
680         ApplicationInformationEventPrivateDataPtr privData(new ApplicationInformationEventPrivateData(onInstalledCbm, onUpdatedCbm, onUninstalledCbm));
681         Try {
682                 IApplicationPtr applications(priv->getObject());
683                 EventInstalledApplicationChangedEmitterPtr emitter(new EventInstalledApplicationChangedEmitter);
684                 emitter->setListener(&ApplicationListener::getInstance());
685                 emitter->setEventPrivateData(StaticPointerCast<IEventPrivateData>(privData));
686                 unsigned long id = applications->addApplicationInformationEventListener(emitter);
687                 LogInfo("id = "<<id);
688                 if(id == 0)
689                         Throw(WrtDeviceApis::Commons::UnsupportedException);
690
691                 return converter->toJSValueRef(id);
692         } Catch (WrtDeviceApis::Commons::ConversionException){
693                 return JSTizenExceptionFactory::postException(context, exception,JSTizenException::TYPE_MISMATCH_ERROR, "Type mistmatch error");
694         } Catch (WrtDeviceApis::Commons::UnsupportedException){
695                 return JSTizenExceptionFactory::postException(context, exception,JSTizenException::NOT_SUPPORTED_ERROR, "Not supported or already registered"); 
696         } Catch (WrtDeviceApis::Commons::InvalidArgumentException){
697                 onUpdatedCbm->callOnError(JSTizenExceptionFactory::makeErrorObject(context,JSTizenException::INVALID_VALUES_ERROR,"Invalid value error"));
698                 return JSValueMakeUndefined(context);
699         } Catch (WrtDeviceApis::Commons::NullPointerException){
700                 onUpdatedCbm->callOnError(JSTizenExceptionFactory::makeErrorObject(context,JSTizenException::UNKNOWN_ERROR,"Unknown error"));
701                 return JSValueMakeUndefined(context);
702         } Catch(WrtDeviceApis::Commons::Exception){
703                 LogError("Exception: " << _rethrown_exception.GetMessage() << " Code: " << _rethrown_exception.getCode());
704                 return JSTizenExceptionFactory::postException(context, exception,JSTizenException::UNKNOWN_ERROR, "Unknown error");
705         }
706 }
707
708 JSValueRef JSApplication::removeApplicationInformationEventListener(JSContextRef context,
709         JSObjectRef object,
710         JSObjectRef thisObject,
711         size_t argumentCount,
712         const JSValueRef arguments[],
713         JSValueRef* exception)
714 {
715     JSApplicationPriv *priv = static_cast<JSApplicationPriv*>(JSObjectGetPrivate(thisObject));
716     assert(priv && "Invalid private pointer.");
717         AceSecurityStatus status = APPLICATION_CHECK_ACCESS(
718                 priv->getContext(),
719                 APPLICATION_FUNCTION_API_REMOVE_APPLICATION_INFORMATION_EVENT_LISTENER);
720         TIZEN_SYNC_ACCESS_HANDLER(status, context, exception);
721     ApplicationConverterFactory::ConverterType converter = ApplicationConverterFactory::getConverter(context);
722     Try
723     {
724         IApplicationPtr applications = priv->getObject();
725         assert(applications && "Application object not present.");
726
727                 if (argumentCount < 1) {
728                         Throw(WrtDeviceApis::Commons::InvalidArgumentException);
729                 }
730
731                 long id = converter->toLong(arguments[0]);
732         applications->removeApplicationInformationEventListener(id);
733         }Catch (WrtDeviceApis::Commons::InvalidArgumentException){
734                 return JSTizenExceptionFactory::postException(context, exception,JSTizenException::TYPE_MISMATCH_ERROR, "Type mistmatch error");
735         }Catch (WrtDeviceApis::Commons::ConversionException){
736                 return JSTizenExceptionFactory::postException(context, exception,JSTizenException::TYPE_MISMATCH_ERROR, "Type mistmatch error");
737         }Catch (WrtDeviceApis::Commons::NullPointerException){
738                 return JSTizenExceptionFactory::postException(context, exception,JSTizenException::UNKNOWN_ERROR, "Unknown error");
739         }Catch(WrtDeviceApis::Commons::Exception){
740                 LogError("Exception: " << _rethrown_exception.GetMessage() << " Code: " << _rethrown_exception.getCode());
741                 return JSTizenExceptionFactory::postException(context, exception,JSTizenException::UNKNOWN_ERROR, "Unknown error");
742         }
743     return JSValueMakeUndefined(context);
744 }
745
746 JSValueRef JSApplication::launchService(JSContextRef context, 
747         JSObjectRef object, 
748         JSObjectRef thisObject, 
749         size_t argumentCount,
750         const JSValueRef arguments[], 
751         JSValueRef* exception) 
752 {
753         LogInfo("launchService <<<");
754         LogDebug("argumentConunt:" << argumentCount);
755         JSApplicationPriv *priv = static_cast<JSApplicationPriv*> (JSObjectGetPrivate(thisObject));
756         assert(priv && "Invalid private pointer.");
757         AceSecurityStatus status = APPLICATION_CHECK_ACCESS(
758                 priv->getContext(),
759                 APPLICATION_FUNCTION_API_LAUNCH_SERVICE);       
760         TIZEN_SYNC_ACCESS_HANDLER(status, context, exception);  
761         JSContextRef gContext = priv->getContext();
762
763         ApplicationConverterFactory::ConverterType converter = ApplicationConverterFactory::getConverter(context);
764
765     if ((argumentCount < 1) ||
766                 (JSValueIsNull(context, arguments[0]) ||
767                  JSValueIsUndefined(context, arguments[0]) ||
768                  JSObjectIsFunction(context, converter->toJSObjectRef(arguments[0]))) ||
769                 ( (argumentCount > 1) &&
770                  !JSObjectIsFunction(context, converter->toJSObjectRef(arguments[1]))) ||
771                 ( (argumentCount > 2) &&
772                  !JSObjectIsFunction(context, converter->toJSObjectRef(arguments[2]))) ||
773                 ( (argumentCount > 3) &&
774                  JSObjectIsFunction(context, converter->toJSObjectRef(arguments[3])))) {
775         LogError("Wrong parameters");
776                 return JSTizenExceptionFactory::postException(context, exception,JSTizenException::TYPE_MISMATCH_ERROR, "Type mistmatch error");
777         }
778
779         JSCallbackManagerPtr callbackManager = JSCallbackManager::createObject(gContext);
780         callbackManager->setOnSuccess(arguments[1]);
781         if (argumentCount > 2)
782                 callbackManager->setOnError(arguments[2]);
783
784         try {
785                 ApplicationServicePtr appService;
786                 ApplicationConverterFactory::ConverterType converter = ApplicationConverterFactory::getConverter(context);
787                 appService = converter->toApplicationService(arguments[0]);
788
789                 JSCallbackManagerPtr replyCallbackManager;
790                 if( argumentCount >3)
791                 {
792                         CommonsJavaScript::Validator validator(gContext);
793                         ApplicationServiceReplyCallback result;
794
795                         JSObjectRef obj = JSValueToObject(context, arguments[3], NULL);
796
797                         result.onsuccess = JSUtils::getJSProperty(context, obj, "onSuccess");
798                         
799                         if (!validator.isNullOrUndefined(result.onsuccess) &&
800                                 !validator.isCallback(result.onsuccess)) {
801                                 ThrowMsg(WrtDeviceApis::Commons::ConversionException, "Not a valid callback.");
802                         }
803
804                         result.onfail = JSUtils::getJSProperty(context, obj, "onFailed");
805                         if (!validator.isNullOrUndefined(result.onfail) &&
806                                 !validator.isCallback(result.onfail)) {
807                                 ThrowMsg(WrtDeviceApis::Commons::ConversionException, "Not a valid callback.");
808                         }
809
810                         if(result.onsuccess || result.onfail)
811                         {
812                                 replyCallbackManager = JSCallbackManager::createObject(priv->getContext(), 
813                                                                 result.onsuccess, result.onfail);
814                         }
815                 }
816
817                 LogDebug("replyCallback"<<callbackManager<<replyCallbackManager);
818                 LaunchServicePrivateDataPtr privateData( 
819                         new LaunchServicePrivateData(callbackManager,replyCallbackManager));
820
821                 LogDebug("after LaunchServicePrivateData()");
822
823                 EventLaunchServicePtr event(new EventLaunchService());
824
825                 IApplicationPtr applications(priv->getObject());
826
827                 event->setEventType(EventLaunchService::APPLICATION_SERVICE_LAUNCH);
828                 event->setPrivateData(StaticPointerCast<IEventPrivateData> (privateData));
829                 event->setService(appService); 
830                 event->setForAsynchronousCall(new ApplicationAnswerReceiver(privateData));
831
832                 applications->launchService(event);
833         }Catch (WrtDeviceApis::Commons::ConversionException){
834                 return JSTizenExceptionFactory::postException(context, exception,JSTizenException::TYPE_MISMATCH_ERROR, "Type mistmatch error");
835         }Catch (WrtDeviceApis::Commons::UnsupportedException){
836                 return JSTizenExceptionFactory::postException(context, exception,JSTizenException::NOT_SUPPORTED_ERROR, "Not supported"); 
837         }Catch (WrtDeviceApis::Commons::InvalidArgumentException){
838                 callbackManager->callOnError(JSTizenExceptionFactory::makeErrorObject(context,JSTizenException::INVALID_VALUES_ERROR,"Invalid value error"));
839                 return JSValueMakeUndefined(context);
840         }Catch (WrtDeviceApis::Commons::NullPointerException){
841                 callbackManager->callOnError(JSTizenExceptionFactory::makeErrorObject(context,JSTizenException::UNKNOWN_ERROR,"Unknown error"));
842                 return JSValueMakeUndefined(context);
843         }Catch(WrtDeviceApis::Commons::Exception){
844                 LogError("Exception: " << _rethrown_exception.GetMessage() << " Code: " << _rethrown_exception.getCode());
845                 return JSTizenExceptionFactory::postException(context, exception,JSTizenException::UNKNOWN_ERROR, "Unknown error");
846         }
847
848     return JSValueMakeUndefined(context);       
849 }
850
851 JSValueRef JSApplication::getApplicationService(JSContextRef context, 
852         JSObjectRef object, 
853         JSObjectRef thisObject, 
854         size_t argumentCount,
855         const JSValueRef arguments[], 
856         JSValueRef* exception) 
857 {
858         JSApplicationPriv *priv = static_cast<JSApplicationPriv*> (JSObjectGetPrivate(thisObject));
859
860         LogDebug("enter getApplicationService");
861
862         assert(priv && "Invalid private pointer.");
863         AceSecurityStatus status = APPLICATION_CHECK_ACCESS(
864                 priv->getContext(),
865                 APPLICATION_FUNCTION_API_GET_APPLICATION_SERVICE);
866         TIZEN_SYNC_ACCESS_HANDLER(status, context, exception);
867         
868         ApplicationConverterFactory::ConverterType converter = ApplicationConverterFactory::getConverter(context);
869
870         LogDebug("get EventLaunchServicePtr");
871         EventLaunchServicePtr event(new EventLaunchService());
872         
873         Try
874     {
875                 IApplicationPtr applications(priv->getObject());
876                 event->setEventType(EventLaunchService::APPLICATION_SERVICE_GET_REQUEST);
877                 event->setForSynchronousCall();
878                 LogDebug("call getApplicationService");
879                 applications->getApplicationService(event);
880                 if (event->getExceptionCode() == WrtDeviceApis::Commons::ExceptionCodes::NotFoundException) {
881                         return JSTizenExceptionFactory::postException(context, exception,JSTizenException::NOT_FOUND_ERROR, "Given package is not found");                      
882                 } else if (event->getExceptionCode() == WrtDeviceApis::Commons::ExceptionCodes::UnknownException) {
883                         return JSTizenExceptionFactory::postException(context, exception,JSTizenException::UNKNOWN_ERROR, "Unknown error");
884                 }
885                 LogDebug("return result");
886                 return converter->toJSValueRef(event->getService());
887         }Catch (WrtDeviceApis::Commons::ConversionException){
888                 LogError("== [WS] error on type mismatch");
889                 return JSTizenExceptionFactory::postException(context, exception,JSTizenException::TYPE_MISMATCH_ERROR, "Type mistmatch error");
890         }Catch (WrtDeviceApis::Commons::InvalidArgumentException){
891                 return JSTizenExceptionFactory::postException(context, exception,JSTizenException::INVALID_VALUES_ERROR,"Invalid value error");
892         }Catch (WrtDeviceApis::Commons::NullPointerException){
893                 return JSTizenExceptionFactory::postException(context, exception,JSTizenException::UNKNOWN_ERROR, "Unknown error");
894         }Catch(WrtDeviceApis::Commons::Exception){
895                 LogError("Exception: " << _rethrown_exception.GetMessage() << " Code: " << _rethrown_exception.getCode());
896                 return JSTizenExceptionFactory::postException(context, exception,JSTizenException::UNKNOWN_ERROR, "Unknown error");
897         }
898 }
899
900 }
901 }
902 }