Fixed svace issue
[platform/core/convergence/service-adaptor.git] / adaptor / shop-adaptor / shop-adaptor.c
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 #include <stdio.h>
18 #include <stdlib.h>
19 #include <string.h>
20 #include <dirent.h>
21 #include <dlfcn.h>
22 #include <glib.h>
23
24 #include "shop-adaptor.h"
25 #include "shop-adaptor-log.h"
26
27 /**
28  * Shop adaptor plugin
29  */
30 typedef struct shop_adaptor_plugin_s {
31         shop_adaptor_h                  adaptor;                        /* Adaptor */
32         char                            *path;                          /* Plugin library path */
33         shop_adaptor_plugin_handle_h    handle;                         /* Plugin handle */
34         void                            *dl_handle;                     /* Plugin library handle */
35         int                             ref_counter;                    /* Plugin reference counter */
36         GMutex                          ref_counter_mutex;              /* Plugin reference counter mutex */
37         shop_adaptor_plugin_listener_h  plugin_listener;                /* Plugin callback listener */
38         GMutex                          plugin_listener_mutex;          /* Plugin callback listener mutex */
39 } shop_adaptor_plugin_t;
40
41 /**
42  * Shop adaptor
43  */
44 typedef struct shop_adaptor_s {
45         GMutex  shop_adaptor_mutex;             /* Adaptor mutex */
46         int     started;                        /* Started flag */
47         char    *plugins_dir;                   /* Plugins directory path */
48         GList   *plugins;                       /* List of loaded plugins */
49         GMutex  plugins_mutex;                  /* Plugin list mutex */
50         GList   *adaptor_listeners;             /* List of vservice channel listener (for now not effective) */
51         GMutex  adaptor_listeners_mutex;        /* Listener list mutex */
52 } shop_adaptor_t;
53
54 /**
55  * Creates plugin
56  */
57 static shop_adaptor_plugin_h shop_adaptor_create_plugin(const char *plugin_path);
58
59 /**
60  * Destroys plugin and deletes all resources associated with it
61  */
62 static void shop_adaptor_destroy_plugin(shop_adaptor_plugin_h plugin);
63
64 /**
65  * Loads plugins from selected directory
66  */
67 static int shop_adaptor_load_plugins_from_directory(shop_adaptor_h adaptor, const char *dir_path);
68
69 /**
70  * Checks if plugin is loaded by selected plugin adaptor
71  */
72 static int shop_adaptor_has_plugin(shop_adaptor_h adaptor, shop_adaptor_plugin_h plugin);
73
74 /**
75  * Increases adaptor's plugin references counter
76  */
77 static void shop_adaptor_plugin_ref(shop_adaptor_plugin_h);
78
79 /**
80  * Decreases adaptor's plugin references counter
81  */
82 static void shop_adaptor_plugin_unref(shop_adaptor_plugin_h);
83
84 /* //------------------------------------------------------------------------
85    // Functions implementations
86    //------------------------------------------------------------------------ */
87
88 /* //////////////////////////////////////////////////////
89    // Mandatory: External adaptor management function
90    ////////////////////////////////////////////////////// */
91
92 EXPORT_API
93 shop_adaptor_h shop_adaptor_create(const char *plugins_dir)
94 {
95         shop_adaptor_h shop_adaptor = (shop_adaptor_h) malloc(sizeof(shop_adaptor_t));
96         if (NULL == shop_adaptor) {
97             return NULL;
98         }
99
100         shop_adaptor->started = 0;
101         shop_adaptor->plugins_dir = strdup(plugins_dir);
102
103         g_mutex_init(&shop_adaptor->shop_adaptor_mutex);
104         g_mutex_init(&shop_adaptor->plugins_mutex);
105         g_mutex_init(&shop_adaptor->adaptor_listeners_mutex);
106
107         g_mutex_lock(&shop_adaptor->adaptor_listeners_mutex);
108         shop_adaptor->adaptor_listeners = NULL;
109         g_mutex_unlock(&shop_adaptor->adaptor_listeners_mutex);
110
111         g_mutex_lock(&shop_adaptor->plugins_mutex);
112         shop_adaptor->plugins = NULL;
113         g_mutex_unlock(&shop_adaptor->plugins_mutex);
114
115         return shop_adaptor;
116
117 }
118
119 EXPORT_API
120 void shop_adaptor_destroy(shop_adaptor_h adaptor)
121 {
122         if (NULL == adaptor) {
123                 shop_adaptor_error("Invalid argument");
124                 return ;
125         }
126
127         g_mutex_lock(&adaptor->shop_adaptor_mutex);
128         if (adaptor->started) {
129                 shop_adaptor_error("Shop adaptor is running. Forcing stop before destroy");
130                 shop_adaptor_stop(adaptor);
131         }
132
133         g_mutex_lock(&adaptor->plugins_mutex);
134         if (NULL != adaptor->plugins) {
135                 g_list_free_full(adaptor->plugins, (GDestroyNotify) shop_adaptor_plugin_unref);
136                 adaptor->plugins = NULL;
137         }
138         g_mutex_unlock(&adaptor->plugins_mutex);
139
140         g_mutex_lock(&adaptor->adaptor_listeners_mutex);
141         if (NULL != adaptor->adaptor_listeners) {
142                 g_list_free(adaptor->adaptor_listeners);
143                 adaptor->adaptor_listeners = NULL;
144         }
145         g_mutex_unlock(&adaptor->adaptor_listeners_mutex);
146
147         /*TODO */
148         /*please add destroying lisners if it needed, currently it is not needed */
149
150         free(adaptor->plugins_dir);
151         adaptor->plugins_dir = NULL;
152
153         g_mutex_unlock(&adaptor->shop_adaptor_mutex);
154
155         free(adaptor);
156 }
157
158 EXPORT_API
159 int shop_adaptor_start(shop_adaptor_h adaptor)
160 {
161         shop_adaptor_debug("Starting shop adaptor");
162         if (NULL == adaptor) {
163                 shop_adaptor_error("Invalid argument");
164                 return SHOP_ADAPTOR_ERROR_INVALID_ARGUMENT;
165         }
166
167         g_mutex_lock(&adaptor->shop_adaptor_mutex);
168         int result = SHOP_ADAPTOR_ERROR_NONE;
169         if (adaptor->started) {
170                 shop_adaptor_error("Storage adaptor is already started");
171                 result = SHOP_ADAPTOR_ERROR_START;
172         } else {
173                 adaptor->started = 1;
174                 result = shop_adaptor_load_plugins_from_directory(adaptor, adaptor->plugins_dir);
175                 if (SHOP_ADAPTOR_ERROR_NONE != result) {
176                         adaptor->started = 0;
177                         shop_adaptor_error("Could not load plugins from directory");
178                 } else {
179                         shop_adaptor_debug("Storage adaptor started successfully");
180                 }
181         }
182         g_mutex_unlock(&adaptor->shop_adaptor_mutex);
183
184         return result;
185 }
186
187 /**
188  * Stops shop adaptor.
189  */
190 EXPORT_API
191 int shop_adaptor_stop(shop_adaptor_h adaptor)
192 {
193         if (NULL == adaptor) {
194                 shop_adaptor_error("Invalid argument");
195                 return SHOP_ADAPTOR_ERROR_INVALID_ARGUMENT;
196         }
197
198         g_mutex_lock(&adaptor->shop_adaptor_mutex);
199         int result = SHOP_ADAPTOR_ERROR_NONE;
200         if (!adaptor->started) {
201                 result = SHOP_ADAPTOR_ERROR_START;
202         } else {
203                 if (NULL != adaptor->plugins) {
204                         g_mutex_lock(&adaptor->plugins_mutex);
205                         g_list_free_full(adaptor->plugins, (GDestroyNotify) shop_adaptor_plugin_unref);
206                         adaptor->plugins = NULL;
207                         g_mutex_unlock(&adaptor->plugins_mutex);
208                 }
209                 adaptor->started = 0;
210                 shop_adaptor_debug("Shop adaptor stopped");
211         }
212
213         g_mutex_unlock(&adaptor->shop_adaptor_mutex);
214         return result;
215 }
216
217 /**
218  * Registers plugin state listener
219  */
220 EXPORT_API
221 int shop_adaptor_register_listener(shop_adaptor_h adaptor, shop_adaptor_listener_h listener)
222 {
223         if ((NULL == adaptor) || (NULL == listener)) {
224                 shop_adaptor_error("Invalid argument");
225                 return SHOP_ADAPTOR_ERROR_INVALID_ARGUMENT;
226         }
227
228         g_mutex_lock(&adaptor->adaptor_listeners_mutex);
229
230         adaptor->adaptor_listeners = g_list_append(adaptor->adaptor_listeners, listener);
231
232         g_mutex_unlock(&adaptor->adaptor_listeners_mutex);
233
234         return SHOP_ADAPTOR_ERROR_NONE;
235 }
236
237 /**
238  * Unregisters plugin state listener
239  */
240 EXPORT_API
241 int shop_adaptor_unregister_listener(shop_adaptor_h adaptor, shop_adaptor_listener_h listener)
242 {
243         if (NULL == adaptor)  {
244                 shop_adaptor_error("Invalid argument (adaptor)");
245                 if (NULL != listener) {
246                         free(listener);
247                         listener = NULL;
248                 }
249                 return SHOP_ADAPTOR_ERROR_INVALID_ARGUMENT;
250         }
251         if (NULL == listener) {
252                 shop_adaptor_error("Invalid argument (listener)");
253                 return SHOP_ADAPTOR_ERROR_INVALID_ARGUMENT;
254         }
255
256         g_mutex_lock(&adaptor->adaptor_listeners_mutex);
257
258         if (NULL == g_list_find(adaptor->adaptor_listeners, listener)) {
259                 g_mutex_unlock(&adaptor->adaptor_listeners_mutex);
260                 shop_adaptor_error("Could not find listener");
261                 free(listener);
262                 return SHOP_ADAPTOR_ERROR_NOT_FOUND;
263         }
264
265         adaptor->adaptor_listeners = g_list_remove(adaptor->adaptor_listeners, listener);
266         free(listener);
267
268         g_mutex_unlock(&adaptor->adaptor_listeners_mutex);
269
270         return SHOP_ADAPTOR_ERROR_NONE;
271 }
272
273 /* /////////////////////////////////////////////////////////////
274    // Plugin create / destroy / ref. count / get plugin name
275    ///////////////////////////////////////////////////////////// */
276 static shop_adaptor_plugin_h shop_adaptor_create_plugin(const char *plugin_path)
277 {
278         if (NULL == plugin_path) {
279                 shop_adaptor_error("Invalid argument");
280                 return NULL;
281         }
282
283         void *dl_handle = dlopen(plugin_path, RTLD_LAZY);
284         if (NULL == dl_handle) {
285                 shop_adaptor_error("Could not load plugin %s: %s", plugin_path, dlerror());
286                 return NULL;
287         }
288
289         shop_adaptor_plugin_handle_h (*get_adaptee_handle)(void) = NULL;
290
291         get_adaptee_handle = (shop_adaptor_plugin_handle_h (*)(void)) (dlsym(dl_handle, "create_plugin_handle"));
292         if (NULL == get_adaptee_handle) {
293                 dlclose(dl_handle);
294                 shop_adaptor_error("Could not get function pointer to create_plugin_handle");
295                 return NULL;
296         }
297
298         plugin_req_enter();
299         shop_adaptor_plugin_handle_h handle = get_adaptee_handle();
300         plugin_req_exit_void();
301
302         if (NULL == handle) {
303                 dlclose(dl_handle);
304                 shop_adaptor_error("Could not get adaptee handle");
305                 return NULL;
306         }
307
308         shop_adaptor_plugin_h plugin = (shop_adaptor_plugin_h) malloc(sizeof(shop_adaptor_plugin_t));
309         if (NULL == plugin) {
310                 dlclose(dl_handle);
311                 shop_adaptor_error("Could not create plugin object");
312                 return NULL;
313         }
314
315         plugin->path = g_strdup(plugin_path);
316         plugin->handle = handle;
317         plugin->dl_handle = dl_handle;
318         plugin->ref_counter = 0;
319
320         g_mutex_init(&plugin->ref_counter_mutex);
321         g_mutex_init(&plugin->plugin_listener_mutex);
322
323         shop_adaptor_plugin_listener_h listener =
324                         (shop_adaptor_plugin_listener_h) malloc(sizeof(shop_adaptor_plugin_listener_t));
325
326         plugin_req_enter();
327         plugin->handle->set_listener(listener);
328         plugin_req_exit_void();
329         g_mutex_lock(&plugin->plugin_listener_mutex);
330         plugin->plugin_listener = listener;
331         g_mutex_unlock(&plugin->plugin_listener_mutex);
332
333         return plugin;
334 }
335
336 static void shop_adaptor_destroy_plugin(shop_adaptor_plugin_h plugin)
337 {
338         if (NULL == plugin) {
339                 shop_adaptor_error("Invalid argument");
340                 return;
341         }
342
343         if (NULL != plugin->handle) {
344                 plugin->handle->destroy_handle(plugin->handle);
345
346                 g_mutex_lock(&plugin->plugin_listener_mutex);
347                 plugin_req_enter();
348                 plugin->handle->unset_listener();
349                 plugin_req_exit_void();
350                 g_mutex_unlock(&plugin->plugin_listener_mutex);
351
352                 plugin->handle = NULL;
353         }
354
355         if (NULL != plugin->dl_handle) {
356                 dlclose(plugin->dl_handle);
357                 plugin->dl_handle = NULL;
358         }
359
360         free(plugin->path);
361         plugin->path = NULL;
362
363         free(plugin);
364 }
365
366 static int shop_adaptor_load_plugins_from_directory(shop_adaptor_h adaptor, const char *dir_path)
367 {
368         char *plugin_path = NULL;
369         DIR *dir = NULL;
370         struct dirent dir_entry, *result = NULL;
371
372         shop_adaptor_debug("Starting load plugins from directory");
373
374         if ((NULL == adaptor) || (NULL == dir_path)) {
375                 shop_adaptor_error("Invalid argument");
376                 return SHOP_ADAPTOR_ERROR_INVALID_ARGUMENT;
377         }
378
379         dir = opendir(dir_path);
380         if (NULL == dir) {
381                 shop_adaptor_error("Could not open dir path (%s)", dir_path);
382                 return SHOP_ADAPTOR_ERROR_NOT_FOUND;
383         }
384
385         int ret = SHOP_ADAPTOR_ERROR_NONE;
386         while (0 == (readdir_r(dir, &dir_entry, &result))) {
387
388                 if (NULL == result) {
389                         shop_adaptor_error("Could not open directory %s", plugin_path);
390                         break;
391                 }
392
393                 if (dir_entry.d_type & DT_DIR) {
394                         continue;
395                 }
396
397                 plugin_path = g_strconcat(dir_path, "/", dir_entry.d_name, NULL);
398                 shop_adaptor_plugin_h plugin = shop_adaptor_create_plugin(plugin_path);
399
400                 if (NULL != plugin) {
401                         shop_adaptor_debug("Loaded plugin: %s", plugin_path);
402                         plugin->adaptor = adaptor;
403                         shop_adaptor_plugin_ref(plugin);
404                         g_mutex_lock(&adaptor->plugins_mutex);
405                         adaptor->plugins = g_list_append(adaptor->plugins, plugin);
406                         g_mutex_unlock(&adaptor->plugins_mutex);
407                 } else {
408                         shop_adaptor_error("Could not load plugin %s", plugin_path);
409                 }
410
411                 free(plugin_path);
412                 plugin_path = NULL;
413         }
414
415         shop_adaptor_debug("End load plugins from directory");
416         closedir(dir);
417         return ret;
418 }
419
420
421 static int shop_adaptor_has_plugin(shop_adaptor_h adaptor, shop_adaptor_plugin_h plugin)
422 {
423         if ((NULL == adaptor) || (NULL == plugin)) {
424                 shop_adaptor_error("Invalid argument");
425                 return 0;
426         }
427
428         int result = 0;
429
430         g_mutex_lock(&adaptor->plugins_mutex);
431         if (NULL != g_list_find(adaptor->plugins, plugin)) {
432                 result = 1;
433         }
434         g_mutex_unlock(&adaptor->plugins_mutex);
435
436         return result;
437 }
438
439 static void shop_adaptor_plugin_ref(shop_adaptor_plugin_h plugin)
440 {
441         if (NULL == plugin) {
442                 shop_adaptor_error("Invalid argument");
443                 return;
444         }
445
446         g_mutex_lock(&plugin->ref_counter_mutex);
447         plugin->ref_counter = plugin->ref_counter + 1;
448         if (NULL != plugin->handle) {
449                 shop_adaptor_info("plugin name : %s, ref_counter: %d", plugin->handle->plugin_uri, plugin->ref_counter);
450         } else {
451                 shop_adaptor_info("ref_counter : %d", plugin->ref_counter);
452         }
453         g_mutex_unlock(&plugin->ref_counter_mutex);
454 }
455
456 static void shop_adaptor_plugin_unref(shop_adaptor_plugin_h plugin)
457 {
458         if (NULL == plugin) {
459                 shop_adaptor_error("Invalid argument");
460                 return ;
461         }
462
463         int should_destroy = 0;
464
465         g_mutex_lock(&plugin->ref_counter_mutex);
466         plugin->ref_counter = plugin->ref_counter - 1;
467
468         if (NULL != plugin->handle) {
469                 shop_adaptor_info("plugin name : %s, ref_counter: %d", plugin->handle->plugin_uri, plugin->ref_counter);
470         } else {
471                 shop_adaptor_info("ref_counter : %d", plugin->ref_counter);
472         }
473
474         if (0 >= plugin->ref_counter) {
475                 should_destroy = 1;
476         }
477         g_mutex_unlock(&plugin->ref_counter_mutex);
478
479         if (should_destroy) {
480                 shop_adaptor_debug("Plugin is being destroyed");
481                 shop_adaptor_destroy_plugin(plugin);
482         }
483 }
484
485 /**
486  * Refresh access token
487  */
488 EXPORT_API
489 shop_error_code_t shop_adaptor_refresh_access_token(shop_adaptor_plugin_context_h context,
490                                                 const char *new_access_token)
491 {
492         if ((NULL == context) || (NULL == new_access_token) || (0 >= strlen(new_access_token))) {
493                 return SHOP_ADAPTOR_ERROR_INVALID_ARGUMENT;
494         }
495         shop_adaptor_debug("New access token : %s", new_access_token);
496
497         free(context->access_token);
498         context->access_token = NULL;
499         context->access_token = strdup(new_access_token);
500
501         return SHOP_ADAPTOR_ERROR_NONE;
502 }
503
504 EXPORT_API
505 shop_error_code_t shop_adaptor_refresh_uid(shop_adaptor_plugin_context_h context,
506                 const char *new_uid)
507 {
508         if ((NULL == context) || (NULL == new_uid) || (0 >= strlen(new_uid))) {
509                 return SHOP_ADAPTOR_ERROR_INVALID_ARGUMENT;
510         }
511         shop_adaptor_debug("New uid : %s", new_uid);
512
513         free(context->duid);
514         context->duid = NULL;
515         context->duid = strdup(new_uid);
516
517         return SHOP_ADAPTOR_ERROR_NONE;
518 }
519
520 /* //////////////////////////////////////////////////////
521    // Create / Destroy error code
522    ////////////////////////////////////////////////////// */
523 shop_adaptor_error_code_h shop_adaptor_create_error_code(const int64_t code, const char *msg)
524 {
525         if (NULL == msg) {
526                 return NULL;
527         }
528
529         shop_adaptor_error_code_h error_code =
530                         (shop_adaptor_error_code_h) malloc(sizeof(shop_adaptor_error_code_t));
531         if (NULL == error_code) {
532             return NULL;
533         }
534
535         error_code->code = code;
536         error_code->msg = strdup(msg);
537
538         return error_code;
539 }
540
541 void shop_adaptor_destroy_error_code(shop_adaptor_error_code_h *error_code)
542 {
543         if ((NULL != error_code) && (NULL != (*error_code))) {
544                 free((*error_code)->msg);
545                 (*error_code)->msg = NULL;
546                 free(*error_code);
547                 *error_code = NULL;
548         }
549 }
550
551
552 /* //////////////////////////////////////////////////////
553    // Plugin context create / destroy
554    ////////////////////////////////////////////////////// */
555 shop_adaptor_plugin_context_h shop_adaptor_create_plugin_context(shop_adaptor_plugin_h plugin, char *plugin_uri, char *duid, char *access_token, char *app_id, char *apptype)
556 {
557         shop_adaptor_debug("Starting shop_adaptor_create_plugin_context");
558
559         if (NULL == plugin) {
560                 shop_adaptor_error("Invalid argument");
561                 return NULL;
562         }
563
564         if (NULL != plugin->handle) {
565                 shop_adaptor_plugin_context_h plugin_context = NULL;
566
567                 plugin_req_enter();
568                 plugin->handle->create_context(&plugin_context, duid, access_token, app_id, apptype);
569                 plugin_req_exit_void();
570
571                 plugin_context->plugin_uri = strdup(plugin->handle->plugin_uri);
572                 return plugin_context;
573         } else {
574                 shop_adaptor_error("Plugin handle is null");
575         }
576
577         shop_adaptor_debug("End shop_adaptor_create_plugin_context");
578         return NULL;
579 }
580
581 void shop_adaptor_destroy_plugin_context(shop_adaptor_plugin_h plugin, shop_adaptor_plugin_context_h plugin_context)
582 {
583         shop_adaptor_warning("Starting shop_adaptor_get_plugin_by_name");
584
585         if ((NULL == plugin) || (NULL == plugin_context)) {
586                 shop_adaptor_error("Invalid argument");
587                 return;
588         }
589
590         if (NULL != plugin->handle) {
591                 plugin_req_enter();
592                 plugin->handle->destroy_context(plugin_context);
593                 plugin_req_exit_void();
594         } else {
595                 shop_adaptor_error("Plugin handle is null");
596         }
597 }
598
599 /* //////////////////////////////////////////////////////
600    // Get plugin by plugin name
601    ////////////////////////////////////////////////////// */
602 shop_adaptor_plugin_h shop_adaptor_get_plugin_by_name(shop_adaptor_h adaptor, const char *plugin_name)
603 {
604         shop_adaptor_warning("Starting shop_adaptor_get_plugin_by_name");
605
606         if ((NULL == adaptor) || (NULL == plugin_name)) {
607                 shop_adaptor_error("Invalid argument");
608                 return NULL;
609         }
610
611         shop_adaptor_plugin_h plugin = NULL;
612         g_mutex_lock(&adaptor->plugins_mutex);
613         int count = g_list_length(adaptor->plugins);
614         int i = 0;
615         for (i = 0; i < count; i++) {
616                 shop_adaptor_plugin_h temp_plugin = (shop_adaptor_plugin_h)g_list_nth_data(adaptor->plugins, i);
617                 if (NULL != temp_plugin) {
618                         if (0 == strcmp(temp_plugin->handle->plugin_uri, plugin_name)) {
619                                 shop_adaptor_plugin_ref(temp_plugin);
620                                 plugin = temp_plugin;
621                                 g_mutex_unlock(&adaptor->plugins_mutex);
622                                 return plugin;
623                         }
624                 }
625         }
626         g_mutex_unlock(&adaptor->plugins_mutex);
627
628         if (NULL == plugin) {
629                 shop_adaptor_debug("Plugin is not found by name");
630         }
631
632         return plugin;
633 }
634
635 /* //////////////////////////////////////////////////////
636    // Plugin load / unload / get plugin list
637    ////////////////////////////////////////////////////// */
638 int shop_adaptor_load_plugin(shop_adaptor_h adaptor, const char *plugin_path)
639 {
640         if ((NULL == adaptor) || (NULL == plugin_path)) {
641                 shop_adaptor_error("Invalid argument");
642                 return SHOP_ADAPTOR_ERROR_INVALID_ARGUMENT;
643         }
644
645         if (!adaptor->started) {
646                 shop_adaptor_error("Storage adaptor is not started");
647                 return SHOP_ADAPTOR_ERROR_START;
648         }
649
650         shop_adaptor_plugin_h plugin = shop_adaptor_create_plugin(plugin_path);
651         if (NULL == plugin) {
652                 shop_adaptor_error("Could not load plugin %s", plugin_path);
653                 return SHOP_ADAPTOR_ERROR_CREATE;
654         }
655
656         plugin->adaptor = adaptor;
657         shop_adaptor_plugin_ref(plugin);
658
659         g_mutex_lock(&adaptor->plugins_mutex);
660         adaptor->plugins = g_list_append(adaptor->plugins, plugin);
661         g_mutex_unlock(&adaptor->plugins_mutex);
662
663         return SHOP_ADAPTOR_ERROR_NONE;
664 }
665
666 int shop_adaptor_unload_plugin(shop_adaptor_h adaptor, shop_adaptor_plugin_h plugin)
667 {
668         if ((NULL == adaptor) || (NULL == plugin)) {
669                 shop_adaptor_error("Invalid argument");
670                 return SHOP_ADAPTOR_ERROR_INVALID_ARGUMENT;
671         }
672
673         if (!adaptor->started) {
674                 shop_adaptor_error("Storage adaptor is not started");
675                 return SHOP_ADAPTOR_ERROR_START;
676         }
677
678         if (!shop_adaptor_has_plugin(adaptor, plugin)) {
679                 shop_adaptor_error("Storage adaptor has no plugin");
680                 return SHOP_ADAPTOR_ERROR_NOT_FOUND;
681         }
682
683         plugin->adaptor = NULL;
684
685         g_mutex_lock(&adaptor->plugins_mutex);
686         adaptor->plugins = g_list_remove(adaptor->plugins, plugin);
687         g_mutex_unlock(&adaptor->plugins_mutex);
688
689         shop_adaptor_plugin_unref(plugin);
690
691         return SHOP_ADAPTOR_ERROR_NONE;
692 }
693
694 GList *shop_adaptor_get_plugins(shop_adaptor_h adaptor)
695 {
696         if (NULL == adaptor) {
697                 shop_adaptor_error("Invalid argument");
698                 return NULL;
699         }
700
701         GList *plugins = NULL;
702
703         g_mutex_lock(&adaptor->plugins_mutex);
704         int plugins_count = g_list_length(adaptor->plugins);
705         int i;
706         for (i = 0; i < plugins_count; i++) {
707                 shop_adaptor_plugin_h plugin = (shop_adaptor_plugin_h)g_list_nth_data(adaptor->plugins, i);
708                 if (NULL != plugin) {
709                         shop_adaptor_plugin_ref(plugin);
710                         plugins = g_list_append(plugins, plugin);
711                 }
712         }
713         g_mutex_unlock(&adaptor->plugins_mutex);
714
715         return plugins;
716
717 }
718
719 EXPORT_API
720 shop_error_code_t shop_adaptor_set_server_info(shop_adaptor_plugin_h plugin,
721                                                 shop_adaptor_plugin_context_h context,
722                                                 GHashTable *server_info,
723                                                 shop_adaptor_error_code_h *error_code)
724 {
725         if ((NULL == plugin) || (NULL == context)) {
726                 shop_adaptor_error("Invalid argument");
727
728                 *error_code = shop_adaptor_create_error_code((int64_t) SHOP_ADAPTOR_ERROR_INVALID_ARGUMENT,
729                                                                 "Invalid argument (plugin or context)");
730
731                 return SHOP_ADAPTOR_ERROR_INVALID_ARGUMENT;
732         }
733
734         if (NULL == plugin->handle) {
735                 shop_adaptor_error("Plugin handle is null");
736
737                 *error_code = shop_adaptor_create_error_code((int64_t) SHOP_ADAPTOR_ERROR_INVALID_HANDLE,
738                                                                 "Plugin handle is null");
739
740                 return SHOP_ADAPTOR_ERROR_INVALID_HANDLE;
741         }
742
743         shop_error_code_t ret;
744         plugin_req_enter();
745         ret = plugin->handle->set_server_info(context, server_info, error_code);
746         plugin_req_exit(ret, plugin, error_code);
747
748         return ret;
749 }
750
751 /* ////////////////////////////////////////////////////////////
752    // Adaptor Plugin call Functions
753    //////////////////////////////////////////////////////////// */
754 EXPORT_API
755 shop_error_code_t shop_adaptor_get_item_list_v1(shop_adaptor_plugin_h plugin, shop_adaptor_plugin_context_h context, shop_adaptor_shop_info_s *info, void *user_data, shop_adaptor_shop_item_s ***items, unsigned int *items_len, shop_adaptor_error_code_h *error_code, void **server_data)
756 {
757         if ((NULL == plugin) || (NULL == context)) {
758                 shop_adaptor_error("Invalid argument");
759
760                 *error_code = shop_adaptor_create_error_code(
761                                 (int64_t) SHOP_ADAPTOR_ERROR_INVALID_ARGUMENT,
762                                 "Invalid argument (plugin or context)");
763
764                 return SHOP_ADAPTOR_ERROR_INVALID_ARGUMENT;
765         }
766
767         if (NULL == plugin->handle) {
768                 shop_adaptor_error("Plugin handle is null");
769
770                 *error_code = shop_adaptor_create_error_code(
771                                 (int64_t) SHOP_ADAPTOR_ERROR_INVALID_HANDLE,
772                                 "Plugin handle is null");
773
774                 return SHOP_ADAPTOR_ERROR_INVALID_HANDLE;
775         }
776
777         shop_error_code_t ret;
778         plugin_req_enter();
779         ret = plugin->handle->get_item_list_v1(context, info, user_data, items, items_len, error_code, server_data);
780         plugin_req_exit(ret, plugin, error_code);
781
782         return ret;
783 }
784
785 EXPORT_API
786 shop_error_code_t shop_adaptor_download_item_package_v1(shop_adaptor_plugin_h plugin, shop_adaptor_plugin_context_h context, shop_adaptor_shop_info_s *info, void *user_data, shop_adaptor_shop_item_s **item, shop_adaptor_error_code_h *error_code, void **server_data)
787 {
788         if ((NULL == plugin) || (NULL == context)) {
789                 shop_adaptor_error("Invalid argument");
790
791                 *error_code = shop_adaptor_create_error_code(
792                                 (int64_t) SHOP_ADAPTOR_ERROR_INVALID_ARGUMENT,
793                                 "Invalid argument (plugin or context)");
794
795                 return SHOP_ADAPTOR_ERROR_INVALID_ARGUMENT;
796         }
797
798         if (NULL == plugin->handle) {
799                 shop_adaptor_error("Plugin handle is null");
800
801                 *error_code = shop_adaptor_create_error_code(
802                                 (int64_t) SHOP_ADAPTOR_ERROR_INVALID_HANDLE,
803                                 "Plugin handle is null");
804
805                 return SHOP_ADAPTOR_ERROR_INVALID_HANDLE;
806         }
807
808         shop_error_code_t ret;
809         plugin_req_enter();
810         ret = plugin->handle->download_item_package_v1(context, info, user_data, item, error_code, server_data);
811         plugin_req_exit(ret, plugin, error_code);
812
813         return ret;
814 }
815
816 EXPORT_API
817 shop_error_code_t shop_adaptor_download_sticker_v1(shop_adaptor_plugin_h plugin, shop_adaptor_plugin_context_h context, shop_adaptor_shop_info_s *info, void *user_data, shop_adaptor_shop_item_s **item, shop_adaptor_error_code_h *error_code, void **server_data)
818 {
819         if ((NULL == plugin) || (NULL == context)) {
820                 shop_adaptor_error("Invalid argument");
821
822                 *error_code = shop_adaptor_create_error_code(
823                                 (int64_t) SHOP_ADAPTOR_ERROR_INVALID_ARGUMENT,
824                                 "Invalid argument (plugin or context)");
825
826                 return SHOP_ADAPTOR_ERROR_INVALID_ARGUMENT;
827         }
828
829         if (NULL == plugin->handle) {
830                 shop_adaptor_error("Plugin handle is null");
831
832                 *error_code = shop_adaptor_create_error_code(
833                                 (int64_t) SHOP_ADAPTOR_ERROR_INVALID_HANDLE,
834                                 "Plugin handle is null");
835
836                 return SHOP_ADAPTOR_ERROR_INVALID_HANDLE;
837         }
838
839         shop_error_code_t ret;
840         plugin_req_enter();
841         ret = plugin->handle->download_sticker_v1(context, info, user_data, item, error_code, server_data);
842         plugin_req_exit(ret, plugin, error_code);
843
844         return ret;
845 }
846
847 EXPORT_API
848 shop_error_code_t shop_adaptor_get_panel_url_v1(shop_adaptor_plugin_h plugin, shop_adaptor_plugin_context_h context, shop_adaptor_shop_info_s *info, void *user_data, shop_adaptor_shop_item_s **item, shop_adaptor_error_code_h *error_code, void **server_data)
849 {
850         if ((NULL == plugin) || (NULL == context)) {
851                 shop_adaptor_error("Invalid argument");
852
853                 *error_code = shop_adaptor_create_error_code(
854                                 (int64_t) SHOP_ADAPTOR_ERROR_INVALID_ARGUMENT,
855                                 "Invalid argument (plugin or context)");
856
857                 return SHOP_ADAPTOR_ERROR_INVALID_ARGUMENT;
858         }
859
860         if (NULL == plugin->handle) {
861                 shop_adaptor_error("Plugin handle is null");
862
863                 *error_code = shop_adaptor_create_error_code(
864                                 (int64_t) SHOP_ADAPTOR_ERROR_INVALID_HANDLE,
865                                 "Plugin handle is null");
866
867                 return SHOP_ADAPTOR_ERROR_INVALID_HANDLE;
868         }
869
870         if (NULL == info) {
871                 shop_adaptor_error("info handle is null");
872
873                 *error_code = shop_adaptor_create_error_code(
874                                 (int64_t) SHOP_ADAPTOR_ERROR_INVALID_ARGUMENT,
875                                 "Info handle is null");
876
877                 return SHOP_ADAPTOR_ERROR_INVALID_HANDLE;
878         }
879
880         shop_error_code_t ret;
881         plugin_req_enter();
882         ret = plugin->handle->get_panel_url_v1(context, info, user_data, item, error_code, server_data);
883         plugin_req_exit(ret, plugin, error_code);
884
885         return ret;
886 }