0916b21f6110c4cff153aca435d4f74e5df41234
[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) || (NULL == listener)) {
244                 shop_adaptor_error("Invalid argument");
245                 return SHOP_ADAPTOR_ERROR_INVALID_ARGUMENT;
246         }
247
248         g_mutex_lock(&adaptor->adaptor_listeners_mutex);
249
250         if (NULL == g_list_find(adaptor->adaptor_listeners, listener)) {
251                 g_mutex_unlock(&adaptor->adaptor_listeners_mutex);
252                 shop_adaptor_error("Could not find listener");
253                 free(listener);
254                 return SHOP_ADAPTOR_ERROR_NOT_FOUND;
255         }
256
257         adaptor->adaptor_listeners = g_list_remove(adaptor->adaptor_listeners, listener);
258         free(listener);
259
260         g_mutex_unlock(&adaptor->adaptor_listeners_mutex);
261
262         return SHOP_ADAPTOR_ERROR_NONE;
263 }
264
265 /* /////////////////////////////////////////////////////////////
266    // Plugin create / destroy / ref. count / get plugin name
267    ///////////////////////////////////////////////////////////// */
268 static shop_adaptor_plugin_h shop_adaptor_create_plugin(const char *plugin_path)
269 {
270         if (NULL == plugin_path) {
271                 shop_adaptor_error("Invalid argument");
272                 return NULL;
273         }
274
275         void *dl_handle = dlopen(plugin_path, RTLD_LAZY);
276         if (NULL == dl_handle) {
277                 shop_adaptor_error("Could not load plugin %s: %s", plugin_path, dlerror());
278                 return NULL;
279         }
280
281         shop_adaptor_plugin_handle_h (*get_adaptee_handle)(void) = NULL;
282
283         get_adaptee_handle = (shop_adaptor_plugin_handle_h (*)(void)) (dlsym(dl_handle, "create_plugin_handle"));
284         if (NULL == get_adaptee_handle) {
285                 dlclose(dl_handle);
286                 shop_adaptor_error("Could not get function pointer to create_plugin_handle");
287                 return NULL;
288         }
289
290         plugin_req_enter();
291         shop_adaptor_plugin_handle_h handle = get_adaptee_handle();
292         plugin_req_exit_void();
293
294         if (NULL == handle) {
295                 dlclose(dl_handle);
296                 shop_adaptor_error("Could not get adaptee handle");
297                 return NULL;
298         }
299
300         shop_adaptor_plugin_h plugin = (shop_adaptor_plugin_h) malloc(sizeof(shop_adaptor_plugin_t));
301         if (NULL == plugin) {
302                 dlclose(dl_handle);
303                 shop_adaptor_error("Could not create plugin object");
304                 return NULL;
305         }
306
307         plugin->path = g_strdup(plugin_path);
308         plugin->handle = handle;
309         plugin->dl_handle = dl_handle;
310         plugin->ref_counter = 0;
311
312         g_mutex_init(&plugin->ref_counter_mutex);
313         g_mutex_init(&plugin->plugin_listener_mutex);
314
315         shop_adaptor_plugin_listener_h listener =
316                         (shop_adaptor_plugin_listener_h) malloc(sizeof(shop_adaptor_plugin_listener_t));
317
318         plugin_req_enter();
319         plugin->handle->set_listener(listener);
320         plugin_req_exit_void();
321         g_mutex_lock(&plugin->plugin_listener_mutex);
322         plugin->plugin_listener = listener;
323         g_mutex_unlock(&plugin->plugin_listener_mutex);
324
325         return plugin;
326 }
327
328 static void shop_adaptor_destroy_plugin(shop_adaptor_plugin_h plugin)
329 {
330         if (NULL == plugin) {
331                 shop_adaptor_error("Invalid argument");
332                 return;
333         }
334
335         if (NULL != plugin->handle) {
336                 plugin->handle->destroy_handle(plugin->handle);
337
338                 g_mutex_lock(&plugin->plugin_listener_mutex);
339                 plugin_req_enter();
340                 plugin->handle->unset_listener();
341                 plugin_req_exit_void();
342                 g_mutex_unlock(&plugin->plugin_listener_mutex);
343
344                 plugin->handle = NULL;
345         }
346
347         if (NULL != plugin->dl_handle) {
348                 dlclose(plugin->dl_handle);
349                 plugin->dl_handle = NULL;
350         }
351
352         free(plugin->path);
353         plugin->path = NULL;
354
355         free(plugin);
356 }
357
358 static int shop_adaptor_load_plugins_from_directory(shop_adaptor_h adaptor, const char *dir_path)
359 {
360         char *plugin_path = NULL;
361         DIR *dir = NULL;
362         struct dirent dir_entry, *result = NULL;
363
364         shop_adaptor_debug("Starting load plugins from directory");
365
366         if ((NULL == adaptor) || (NULL == dir_path)) {
367                 shop_adaptor_error("Invalid argument");
368                 return SHOP_ADAPTOR_ERROR_INVALID_ARGUMENT;
369         }
370
371         dir = opendir(dir_path);
372         if (NULL == dir) {
373                 shop_adaptor_error("Could not open dir path (%s)", dir_path);
374                 return SHOP_ADAPTOR_ERROR_NOT_FOUND;
375         }
376
377         int ret = SHOP_ADAPTOR_ERROR_NONE;
378         while (0 == (readdir_r(dir, &dir_entry, &result))) {
379
380                 if (NULL == result) {
381                         shop_adaptor_error("Could not open directory %s", plugin_path);
382                         break;
383                 }
384
385                 if (dir_entry.d_type & DT_DIR) {
386                         continue;
387                 }
388
389                 plugin_path = g_strconcat(dir_path, "/", dir_entry.d_name, NULL);
390                 shop_adaptor_plugin_h plugin = shop_adaptor_create_plugin(plugin_path);
391
392                 if (NULL != plugin) {
393                         shop_adaptor_debug("Loaded plugin: %s", plugin_path);
394                         plugin->adaptor = adaptor;
395                         shop_adaptor_plugin_ref(plugin);
396                         g_mutex_lock(&adaptor->plugins_mutex);
397                         adaptor->plugins = g_list_append(adaptor->plugins, plugin);
398                         g_mutex_unlock(&adaptor->plugins_mutex);
399                 } else {
400                         shop_adaptor_error("Could not load plugin %s", plugin_path);
401                 }
402
403                 free(plugin_path);
404                 plugin_path = NULL;
405         }
406
407         shop_adaptor_debug("End load plugins from directory");
408         closedir(dir);
409         return ret;
410 }
411
412
413 static int shop_adaptor_has_plugin(shop_adaptor_h adaptor, shop_adaptor_plugin_h plugin)
414 {
415         if ((NULL == adaptor) || (NULL == plugin)) {
416                 shop_adaptor_error("Invalid argument");
417                 return 0;
418         }
419
420         int result = 0;
421
422         g_mutex_lock(&adaptor->plugins_mutex);
423         if (NULL != g_list_find(adaptor->plugins, plugin)) {
424                 result = 1;
425         }
426         g_mutex_unlock(&adaptor->plugins_mutex);
427
428         return result;
429 }
430
431 static void shop_adaptor_plugin_ref(shop_adaptor_plugin_h plugin)
432 {
433         if (NULL == plugin) {
434                 shop_adaptor_error("Invalid argument");
435                 return;
436         }
437
438         g_mutex_lock(&plugin->ref_counter_mutex);
439         plugin->ref_counter = plugin->ref_counter + 1;
440         if (NULL != plugin->handle) {
441                 shop_adaptor_info("plugin name : %s, ref_counter: %d", plugin->handle->plugin_uri, plugin->ref_counter);
442         } else {
443                 shop_adaptor_info("ref_counter : %d", plugin->ref_counter);
444         }
445         g_mutex_unlock(&plugin->ref_counter_mutex);
446 }
447
448 static void shop_adaptor_plugin_unref(shop_adaptor_plugin_h plugin)
449 {
450         if (NULL == plugin) {
451                 shop_adaptor_error("Invalid argument");
452                 return ;
453         }
454
455         int should_destroy = 0;
456
457         g_mutex_lock(&plugin->ref_counter_mutex);
458         plugin->ref_counter = plugin->ref_counter - 1;
459
460         if (NULL != plugin->handle) {
461                 shop_adaptor_info("plugin name : %s, ref_counter: %d", plugin->handle->plugin_uri, plugin->ref_counter);
462         } else {
463                 shop_adaptor_info("ref_counter : %d", plugin->ref_counter);
464         }
465
466         if (0 >= plugin->ref_counter) {
467                 should_destroy = 1;
468         }
469         g_mutex_unlock(&plugin->ref_counter_mutex);
470
471         if (should_destroy) {
472                 shop_adaptor_debug("Plugin is being destroyed");
473                 shop_adaptor_destroy_plugin(plugin);
474         }
475 }
476
477 /**
478  * Refresh access token
479  */
480 EXPORT_API
481 shop_error_code_t shop_adaptor_refresh_access_token(shop_adaptor_plugin_context_h context,
482                                                 const char *new_access_token)
483 {
484         if ((NULL == context) || (NULL == new_access_token) || (0 >= strlen(new_access_token))) {
485                 return SHOP_ADAPTOR_ERROR_INVALID_ARGUMENT;
486         }
487         shop_adaptor_debug("New access token : %s", new_access_token);
488
489         free(context->access_token);
490         context->access_token = NULL;
491         context->access_token = strdup(new_access_token);
492
493         return SHOP_ADAPTOR_ERROR_NONE;
494 }
495
496 EXPORT_API
497 shop_error_code_t shop_adaptor_refresh_uid(shop_adaptor_plugin_context_h context,
498                 const char *new_uid)
499 {
500         if ((NULL == context) || (NULL == new_uid) || (0 >= strlen(new_uid))) {
501                 return SHOP_ADAPTOR_ERROR_INVALID_ARGUMENT;
502         }
503         shop_adaptor_debug("New uid : %s", new_uid);
504
505         free(context->duid);
506         context->duid = NULL;
507         context->duid = strdup(new_uid);
508
509         return SHOP_ADAPTOR_ERROR_NONE;
510 }
511
512 /* //////////////////////////////////////////////////////
513    // Create / Destroy error code
514    ////////////////////////////////////////////////////// */
515 shop_adaptor_error_code_h shop_adaptor_create_error_code(const int64_t code, const char *msg)
516 {
517         if (NULL == msg) {
518                 return NULL;
519         }
520
521         shop_adaptor_error_code_h error_code =
522                         (shop_adaptor_error_code_h) malloc(sizeof(shop_adaptor_error_code_t));
523         if (NULL == error_code) {
524             return NULL;
525         }
526
527         error_code->code = code;
528         error_code->msg = strdup(msg);
529
530         return error_code;
531 }
532
533 void shop_adaptor_destroy_error_code(shop_adaptor_error_code_h *error_code)
534 {
535         if ((NULL != error_code) && (NULL != (*error_code))) {
536                 free((*error_code)->msg);
537                 (*error_code)->msg = NULL;
538                 free(*error_code);
539                 *error_code = NULL;
540         }
541 }
542
543
544 /* //////////////////////////////////////////////////////
545    // Plugin context create / destroy
546    ////////////////////////////////////////////////////// */
547 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)
548 {
549         shop_adaptor_debug("Starting shop_adaptor_create_plugin_context");
550
551         if (NULL == plugin) {
552                 shop_adaptor_error("Invalid argument");
553                 return NULL;
554         }
555
556         if (NULL != plugin->handle) {
557                 shop_adaptor_plugin_context_h plugin_context = NULL;
558
559                 plugin_req_enter();
560                 plugin->handle->create_context(&plugin_context, duid, access_token, app_id, apptype);
561                 plugin_req_exit_void();
562
563                 plugin_context->plugin_uri = strdup(plugin->handle->plugin_uri);
564                 return plugin_context;
565         } else {
566                 shop_adaptor_error("Plugin handle is null");
567         }
568
569         shop_adaptor_debug("End shop_adaptor_create_plugin_context");
570         return NULL;
571 }
572
573 void shop_adaptor_destroy_plugin_context(shop_adaptor_plugin_h plugin, shop_adaptor_plugin_context_h plugin_context)
574 {
575         shop_adaptor_warning("Starting shop_adaptor_get_plugin_by_name");
576
577         if ((NULL == plugin) || (NULL == plugin_context)) {
578                 shop_adaptor_error("Invalid argument");
579                 return;
580         }
581
582         if (NULL != plugin->handle) {
583                 plugin_req_enter();
584                 plugin->handle->destroy_context(plugin_context);
585                 plugin_req_exit_void();
586         } else {
587                 shop_adaptor_error("Plugin handle is null");
588         }
589 }
590
591 /* //////////////////////////////////////////////////////
592    // Get plugin by plugin name
593    ////////////////////////////////////////////////////// */
594 shop_adaptor_plugin_h shop_adaptor_get_plugin_by_name(shop_adaptor_h adaptor, const char *plugin_name)
595 {
596         shop_adaptor_warning("Starting shop_adaptor_get_plugin_by_name");
597
598         if ((NULL == adaptor) || (NULL == plugin_name)) {
599                 shop_adaptor_error("Invalid argument");
600                 return NULL;
601         }
602
603         shop_adaptor_plugin_h plugin = NULL;
604         g_mutex_lock(&adaptor->plugins_mutex);
605         int count = g_list_length(adaptor->plugins);
606         int i = 0;
607         for (i = 0; i < count; i++) {
608                 shop_adaptor_plugin_h temp_plugin = (shop_adaptor_plugin_h)g_list_nth_data(adaptor->plugins, i);
609                 if (NULL != temp_plugin) {
610                         if (0 == strcmp(temp_plugin->handle->plugin_uri, plugin_name)) {
611                                 shop_adaptor_plugin_ref(temp_plugin);
612                                 plugin = temp_plugin;
613                                 g_mutex_unlock(&adaptor->plugins_mutex);
614                                 return plugin;
615                         }
616                 }
617         }
618         g_mutex_unlock(&adaptor->plugins_mutex);
619
620         if (NULL == plugin) {
621                 shop_adaptor_debug("Plugin is not found by name");
622         }
623
624         return plugin;
625 }
626
627 /* //////////////////////////////////////////////////////
628    // Plugin load / unload / get plugin list
629    ////////////////////////////////////////////////////// */
630 int shop_adaptor_load_plugin(shop_adaptor_h adaptor, const char *plugin_path)
631 {
632         if ((NULL == adaptor) || (NULL == plugin_path)) {
633                 shop_adaptor_error("Invalid argument");
634                 return SHOP_ADAPTOR_ERROR_INVALID_ARGUMENT;
635         }
636
637         if (!adaptor->started) {
638                 shop_adaptor_error("Storage adaptor is not started");
639                 return SHOP_ADAPTOR_ERROR_START;
640         }
641
642         shop_adaptor_plugin_h plugin = shop_adaptor_create_plugin(plugin_path);
643         if (NULL == plugin) {
644                 shop_adaptor_error("Could not load plugin %s", plugin_path);
645                 return SHOP_ADAPTOR_ERROR_CREATE;
646         }
647
648         plugin->adaptor = adaptor;
649         shop_adaptor_plugin_ref(plugin);
650
651         g_mutex_lock(&adaptor->plugins_mutex);
652         adaptor->plugins = g_list_append(adaptor->plugins, plugin);
653         g_mutex_unlock(&adaptor->plugins_mutex);
654
655         return SHOP_ADAPTOR_ERROR_NONE;
656 }
657
658 int shop_adaptor_unload_plugin(shop_adaptor_h adaptor, shop_adaptor_plugin_h plugin)
659 {
660         if ((NULL == adaptor) || (NULL == plugin)) {
661                 shop_adaptor_error("Invalid argument");
662                 return SHOP_ADAPTOR_ERROR_INVALID_ARGUMENT;
663         }
664
665         if (!adaptor->started) {
666                 shop_adaptor_error("Storage adaptor is not started");
667                 return SHOP_ADAPTOR_ERROR_START;
668         }
669
670         if (!shop_adaptor_has_plugin(adaptor, plugin)) {
671                 shop_adaptor_error("Storage adaptor has no plugin");
672                 return SHOP_ADAPTOR_ERROR_NOT_FOUND;
673         }
674
675         plugin->adaptor = NULL;
676
677         g_mutex_lock(&adaptor->plugins_mutex);
678         adaptor->plugins = g_list_remove(adaptor->plugins, plugin);
679         g_mutex_unlock(&adaptor->plugins_mutex);
680
681         shop_adaptor_plugin_unref(plugin);
682
683         return SHOP_ADAPTOR_ERROR_NONE;
684 }
685
686 GList *shop_adaptor_get_plugins(shop_adaptor_h adaptor)
687 {
688         if (NULL == adaptor) {
689                 shop_adaptor_error("Invalid argument");
690                 return NULL;
691         }
692
693         GList *plugins = NULL;
694
695         g_mutex_lock(&adaptor->plugins_mutex);
696         int plugins_count = g_list_length(adaptor->plugins);
697         int i;
698         for (i = 0; i < plugins_count; i++) {
699                 shop_adaptor_plugin_h plugin = (shop_adaptor_plugin_h)g_list_nth_data(adaptor->plugins, i);
700                 if (NULL != plugin) {
701                         shop_adaptor_plugin_ref(plugin);
702                         plugins = g_list_append(plugins, plugin);
703                 }
704         }
705         g_mutex_unlock(&adaptor->plugins_mutex);
706
707         return plugins;
708
709 }
710
711 EXPORT_API
712 shop_error_code_t shop_adaptor_set_server_info(shop_adaptor_plugin_h plugin,
713                                                 shop_adaptor_plugin_context_h context,
714                                                 GHashTable *server_info,
715                                                 shop_adaptor_error_code_h *error_code)
716 {
717         if ((NULL == plugin) || (NULL == context)) {
718                 shop_adaptor_error("Invalid argument");
719
720                 *error_code = shop_adaptor_create_error_code((int64_t) SHOP_ADAPTOR_ERROR_INVALID_ARGUMENT,
721                                                                 "Invalid argument (plugin or context)");
722
723                 return SHOP_ADAPTOR_ERROR_INVALID_ARGUMENT;
724         }
725
726         if (NULL == plugin->handle) {
727                 shop_adaptor_error("Plugin handle is null");
728
729                 *error_code = shop_adaptor_create_error_code((int64_t) SHOP_ADAPTOR_ERROR_INVALID_HANDLE,
730                                                                 "Plugin handle is null");
731
732                 return SHOP_ADAPTOR_ERROR_INVALID_HANDLE;
733         }
734
735         shop_error_code_t ret;
736         plugin_req_enter();
737         ret = plugin->handle->set_server_info(context, server_info, error_code);
738         plugin_req_exit(ret, plugin, error_code);
739
740         return ret;
741 }
742
743 /* ////////////////////////////////////////////////////////////
744    // Adaptor Plugin call Functions
745    //////////////////////////////////////////////////////////// */
746 EXPORT_API
747 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)
748 {
749         if ((NULL == plugin) || (NULL == context)) {
750                 shop_adaptor_error("Invalid argument");
751
752                 *error_code = shop_adaptor_create_error_code(
753                                 (int64_t) SHOP_ADAPTOR_ERROR_INVALID_ARGUMENT,
754                                 "Invalid argument (plugin or context)");
755
756                 return SHOP_ADAPTOR_ERROR_INVALID_ARGUMENT;
757         }
758
759         if (NULL == plugin->handle) {
760                 shop_adaptor_error("Plugin handle is null");
761
762                 *error_code = shop_adaptor_create_error_code(
763                                 (int64_t) SHOP_ADAPTOR_ERROR_INVALID_HANDLE,
764                                 "Plugin handle is null");
765
766                 return SHOP_ADAPTOR_ERROR_INVALID_HANDLE;
767         }
768
769         shop_error_code_t ret;
770         plugin_req_enter();
771         ret = plugin->handle->get_item_list_v1(context, info, user_data, items, items_len, error_code, server_data);
772         plugin_req_exit(ret, plugin, error_code);
773
774         return ret;
775 }
776
777 EXPORT_API
778 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)
779 {
780         if ((NULL == plugin) || (NULL == context)) {
781                 shop_adaptor_error("Invalid argument");
782
783                 *error_code = shop_adaptor_create_error_code(
784                                 (int64_t) SHOP_ADAPTOR_ERROR_INVALID_ARGUMENT,
785                                 "Invalid argument (plugin or context)");
786
787                 return SHOP_ADAPTOR_ERROR_INVALID_ARGUMENT;
788         }
789
790         if (NULL == plugin->handle) {
791                 shop_adaptor_error("Plugin handle is null");
792
793                 *error_code = shop_adaptor_create_error_code(
794                                 (int64_t) SHOP_ADAPTOR_ERROR_INVALID_HANDLE,
795                                 "Plugin handle is null");
796
797                 return SHOP_ADAPTOR_ERROR_INVALID_HANDLE;
798         }
799
800         shop_error_code_t ret;
801         plugin_req_enter();
802         ret = plugin->handle->download_item_package_v1(context, info, user_data, item, error_code, server_data);
803         plugin_req_exit(ret, plugin, error_code);
804
805         return ret;
806 }
807
808 EXPORT_API
809 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)
810 {
811         if ((NULL == plugin) || (NULL == context)) {
812                 shop_adaptor_error("Invalid argument");
813
814                 *error_code = shop_adaptor_create_error_code(
815                                 (int64_t) SHOP_ADAPTOR_ERROR_INVALID_ARGUMENT,
816                                 "Invalid argument (plugin or context)");
817
818                 return SHOP_ADAPTOR_ERROR_INVALID_ARGUMENT;
819         }
820
821         if (NULL == plugin->handle) {
822                 shop_adaptor_error("Plugin handle is null");
823
824                 *error_code = shop_adaptor_create_error_code(
825                                 (int64_t) SHOP_ADAPTOR_ERROR_INVALID_HANDLE,
826                                 "Plugin handle is null");
827
828                 return SHOP_ADAPTOR_ERROR_INVALID_HANDLE;
829         }
830
831         shop_error_code_t ret;
832         plugin_req_enter();
833         ret = plugin->handle->download_sticker_v1(context, info, user_data, item, error_code, server_data);
834         plugin_req_exit(ret, plugin, error_code);
835
836         return ret;
837 }
838
839 EXPORT_API
840 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)
841 {
842         if ((NULL == plugin) || (NULL == context)) {
843                 shop_adaptor_error("Invalid argument");
844
845                 *error_code = shop_adaptor_create_error_code(
846                                 (int64_t) SHOP_ADAPTOR_ERROR_INVALID_ARGUMENT,
847                                 "Invalid argument (plugin or context)");
848
849                 return SHOP_ADAPTOR_ERROR_INVALID_ARGUMENT;
850         }
851
852         if (NULL == plugin->handle) {
853                 shop_adaptor_error("Plugin handle is null");
854
855                 *error_code = shop_adaptor_create_error_code(
856                                 (int64_t) SHOP_ADAPTOR_ERROR_INVALID_HANDLE,
857                                 "Plugin handle is null");
858
859                 return SHOP_ADAPTOR_ERROR_INVALID_HANDLE;
860         }
861
862         if (NULL == info) {
863                 shop_adaptor_error("info handle is null");
864
865                 *error_code = shop_adaptor_create_error_code(
866                                 (int64_t) SHOP_ADAPTOR_ERROR_INVALID_ARGUMENT,
867                                 "Info handle is null");
868
869                 return SHOP_ADAPTOR_ERROR_INVALID_HANDLE;
870         }
871
872         shop_error_code_t ret;
873         plugin_req_enter();
874         ret = plugin->handle->get_panel_url_v1(context, info, user_data, item, error_code, server_data);
875         plugin_req_exit(ret, plugin, error_code);
876
877         return ret;
878 }