iotivity 0.9.0
[platform/upstream/iotivity.git] / service / protocol-plugin / plugin-manager / src / CpluffAdapter.cpp
1 //******************************************************************
2 //
3 // Copyright 2014 Samsung Electronics All Rights Reserved.
4 //
5 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
6 //
7 // Licensed under the Apache License, Version 2.0 (the "License");
8 // you may not use this file except in compliance with the License.
9 // You may obtain a copy of the License at
10 //
11 //      http://www.apache.org/licenses/LICENSE-2.0
12 //
13 // Unless required by applicable law or agreed to in writing, software
14 // distributed under the License is distributed on an "AS IS" BASIS,
15 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 // See the License for the specific language governing permissions and
17 // limitations under the License.
18 //
19 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
20
21 /// @file CpluffAdapter.cpp
22
23 /// @brief
24
25 #include "CpluffAdapter.h"
26
27 using namespace OIC;
28
29 CpluffAdapter *CpluffAdapter::s_pinstance;
30
31 CpluffAdapter::CpluffAdapter()
32 {
33     m_status = cp_init();
34     m_context = cp_create_context(&m_status);
35     m_cp_plugins = nullptr;
36     m_plugin = nullptr;
37
38     config = Config::Getinstance();
39     std::string pluginpath = config->getPluginPath();
40     if (pluginpath != "")
41     {
42         printf("Current path is %s\n", pluginpath.c_str());
43     }
44     else
45     {
46         fprintf(stderr, "Pluing path does not exist\n");
47         pluginpath = "";
48     }
49     registerAllPlugin(pluginpath);
50 }
51
52 CpluffAdapter::~CpluffAdapter(void)
53 {
54     cp_release_info(m_context, m_cp_plugins);
55     //Auto plugin detection is disabled
56     //m_thread_g.interrupt_all();
57     //m_thread_g.join_all();
58     s_pinstance->deleteinstance();
59     s_pinstance = nullptr;
60 }
61
62 int CpluffAdapter::installPlugin(const std::string path)
63 {
64     char *argv = const_cast<char *>(path.c_str());
65
66     if ((m_plugin = cp_load_plugin_descriptor(m_context, argv, &m_status)) == nullptr)
67     {
68         printf("cp_load_plugin_descriptor failed\n");
69         return false;
70     }
71     else if ((m_status = cp_install_plugin(m_context, m_plugin)) != 0)
72     {
73         if (m_status == CP_ERR_CONFLICT)
74         {
75             printf("Plugin is already installed or conflicts symbol.\n");
76         }
77         printf("cp_install_plugin failed : %d \n" , m_status);
78
79         return false;
80     }
81
82     return true;
83 }
84
85 int CpluffAdapter::findPluginRecursive(const std::string path)
86 {
87     ////////FILELIST////////////
88     File_list file_list;
89     getFileList(file_list, path);
90     File_list::iterator itr;
91     int flag = TRUE;
92     for (itr = file_list.begin(); itr != file_list.end(); itr++)
93     {
94         if (itr->second == true)
95         {
96             //printf("[Direcotry] %s\n",itr->first.c_str());
97         }
98         else
99         {
100             //printf("[FILE] = %s\n" , itr->first.c_str());
101             std::string filepath = itr->first.c_str();
102             int count = 0;
103             for (unsigned int i = 0 ; i < filepath.size(); i++)
104             {
105                 if (filepath.at(i) == '/')
106                 {
107                     count = i;
108                 }
109             }
110             std::string filename = filepath.substr(0, count );
111             if (!installPlugin(filename))
112             {
113                 printf("installPlugin failed path : %s \n", filename.c_str());
114             }
115         }
116     }
117
118     return flag;
119 }
120
121 int CpluffAdapter::loadPluginInfoToManager(const std::string path)
122 {
123     //get plugins information.
124     if ((m_cp_plugins = cp_get_plugins_info(m_context, &m_status, nullptr)) == nullptr)
125     {
126         printf("cp_get_plugins_infor failed\n");
127         return FALSE;
128     }
129     else
130     {
131         printPluginList();
132     }
133
134     for (int i = 0 ; m_cp_plugins[i] != nullptr; i++)
135     {
136         Plugin *plugin = new Plugin;
137         plugin->setValue("Path", m_cp_plugins[i]->plugin_path);
138         plugin->setValue("Language", "CPP");
139         //printf("add filepath %s\n",m_cp_plugins[i]->plugin_path);
140         if (m_cp_plugins[i]->identifier != nullptr)
141         {
142             plugin->setValue("Id", m_cp_plugins[i]->identifier );
143         }
144         else
145         {
146             plugin->setValue("Id", "");
147         }
148
149         if (m_cp_plugins[i]->url != nullptr)
150         {
151             plugin->setValue("Url", m_cp_plugins[i]->url);
152         }
153         else
154         {
155             plugin->setValue("Url", "");
156         }
157
158         if (m_cp_plugins[i]->name != nullptr)
159         {
160             plugin->setValue("Name", m_cp_plugins[i]->name);
161         }
162         else
163         {
164             plugin->setValue("Name", "");
165         }
166
167         if (m_cp_plugins[i]->resourcetype != nullptr)
168         {
169             plugin->setValue("ResourceType", m_cp_plugins[i]->resourcetype);
170         }
171         else
172         {
173             plugin->setValue("ResourceType", "");
174         }
175
176         if (m_cp_plugins[i]->version != nullptr)
177         {
178             plugin->setValue("Version", m_cp_plugins[i]->version);
179         }
180         else
181         {
182             plugin->setValue("Version", "");
183         }
184
185         bool plugin_compare_flag = true;
186         for (unsigned int i = 0 ; i < m_plugins.size(); i++)
187         {
188             if (*plugin == m_plugins[i])
189             {
190                 delete(plugin);
191                 plugin_compare_flag = false;
192                 break;
193             }
194         }
195         if (plugin_compare_flag)
196         {
197             //Auto plugin detection is disabled
198             /*
199             try
200             {
201                 boost::thread *t = new boost::thread(boost::bind(&CpluffAdapter::observePluginPath,
202                                                      //this, (void *)path.c_str()));
203                                                      this, (void *)m_cp_plugins[i]->plugin_path));
204                 m_thread_g.add_thread(t);
205             }
206             catch (...)
207             {
208                 printf("thread throw exception\n");
209             }
210             */
211             m_plugins.push_back(*plugin);
212             delete(plugin);
213         }
214         //printf("plugin size = %d\n",m_plugins.size());
215     }
216
217     return TRUE;
218 }
219
220 int CpluffAdapter::registerPlugin(const std::string path)
221 {
222     //printf("CpluffAdapter register\n");
223     int flag = FALSE;
224
225     if (path == "")
226     {
227         printf("CpluffAdapter path == null\n");
228         return flag;
229     }
230
231     //non recursive
232     if (installPlugin(path))
233     {
234         flag = loadPluginInfoToManager(path);
235     }
236     return flag;
237 }
238
239 int CpluffAdapter::registerAllPlugin(const std::string path)
240 {
241     //printf("CpluffAdapter register\n");
242     int flag = FALSE;
243     if (path == "")
244     {
245         printf("CpluffAdapter path == null\n");
246         return flag;
247     }
248
249     //recursive
250     if (findPluginRecursive(path))
251     {
252         flag = loadPluginInfoToManager(path);
253     }
254     return flag;
255 }
256
257 int CpluffAdapter::unregisterPlugin(Plugin *const plugin)
258 {
259     cp_status_t status;
260     char *argv = nullptr;
261     std::string id = "";
262
263     for (unsigned int i = 0; i < m_plugins.size(); i++)
264     {
265
266         if (*plugin == m_plugins[i])
267         {
268             id = m_plugins[i].getID().c_str();
269             argv = const_cast<char *>(id.c_str());
270             if ((status = cp_uninstall_plugin(m_context, argv)) != 0)
271             {
272                 printf("unregister failed\n");
273                 return FALSE;
274             }
275             m_plugins.erase(m_plugins.begin() + i);
276         }
277     }
278     return TRUE;
279 }
280
281 int CpluffAdapter::unregisterAllPlugin(void)
282 {
283     cp_status_t status;
284     char *argv = nullptr;
285     std::string id = "";
286
287     while (true)
288     {
289         id = m_plugins[0].getID().c_str();
290         argv = const_cast<char *>(id.c_str());
291         if ((status = cp_uninstall_plugin(m_context, argv)) != 0)
292         {
293             printf("unregister failed\n");
294             return FALSE;
295         }
296         m_plugins.erase(m_plugins.begin());
297         if (m_plugins.size() == 0)
298         {
299             break;
300         }
301     }
302
303     return TRUE;
304 }
305
306 std::vector<Plugin> &CpluffAdapter::getAllPlugins(void)
307 {
308     return m_plugins;
309 }
310
311 std::vector<Plugin> *CpluffAdapter::findPlugins(const std::string key, const std::string value)
312 {
313     std::vector<Plugin> *re_plugins;
314
315     re_plugins = new std::vector<Plugin>;
316
317     for (unsigned int i = 0; i < m_plugins.size(); i++)
318     {
319         if (!m_plugins[i].getValueByAttribute(key).compare(value))
320         {
321             re_plugins->push_back(m_plugins[i]);
322         }
323     }
324
325     return re_plugins;
326 }
327 /*
328 Plugin *CpluffAdapter::getPlugin(const std::string plugID)
329 {
330     for (unsigned int i = 0; i < m_plugins.size(); i++)
331     {
332         if (!(m_plugins[i].getID().compare(plugID)))
333         {
334             return &(m_plugins[i]);
335         }
336     }
337
338     return nullptr;
339 }
340 */
341 bool CpluffAdapter::getFileList(File_list &list, const std::string strDir)
342 {
343     struct stat statinfo;
344     memset(&statinfo, 0, sizeof(statinfo));
345     std::string path = strDir;
346     if (0 != lstat(path.c_str(), &statinfo))
347     {
348         printf("OICPlugManager lstat is 0\n");
349         return false;
350     }
351     if (!S_ISDIR(statinfo.st_mode))
352     {
353         printf("%s is not directory", strDir.c_str());
354         return false;
355     }
356
357     DIR *dir;
358     struct dirent *entry;
359
360     if ((dir = opendir(strDir.c_str())) == nullptr)
361     {
362         printf("%s open error", strDir.c_str());
363         return false;
364     }
365
366     while ((entry = readdir(dir)) != nullptr)
367     {
368         memset(&statinfo, 0, sizeof(statinfo));
369         std::string strFilePath = strDir + "/" + entry->d_name;
370         while (strFilePath.find("//") != std::string::npos)
371             strFilePath.replace(strFilePath.find("//"), 2, "/");
372
373         if (0 != lstat(strFilePath.c_str(), &statinfo))
374         {
375             printf("OICPlugManager lstat is 0\n");
376             closedir(dir);
377             return false;
378         }
379
380         if (S_ISDIR(statinfo.st_mode))
381         {
382             if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0)
383                 continue;
384
385             list.insert(std::pair<std::string, bool>(strFilePath, true));
386             std::string strSubDir = strDir + "/" + entry->d_name;
387             getFileList(list, strSubDir);
388         }
389         else
390         {
391             int size = strFilePath.size();
392             std::string so = strFilePath.substr(size - 2, size - 1);
393             if (so  == "so")
394             {
395                 list.insert(std::pair<std::string, bool>(strFilePath, false));
396             }
397         }
398     }
399     closedir(dir);
400
401     return true;
402 }
403
404 const char *CpluffAdapter::state_to_string(int state)
405 {
406     switch (state)
407     {
408         case 0:
409             return "UNINTALLED";
410         case 1:
411             return "INSTALLED";
412         case 2:
413             return "RESOLVED";
414         case 3:
415             return "STARTING";
416         case 4:
417             return "STOPPING";
418         case 5:
419             return "ACTIVE";
420         default:
421             return "Unknown";
422     }
423 }
424
425 void CpluffAdapter::printPluginList()
426 {
427     const char format[] = "  %-30s %-15s %-15s %-20s\n";
428     printf("\n====== Plugins List ======\n");
429     printf(format,
430            "ID",
431            "NAME",
432            "STATE",
433            "TYPE");
434
435     for (int i = 0; m_cp_plugins[i] != nullptr; i++)
436     {
437         printf(format,
438                m_cp_plugins[i]->identifier,
439                m_cp_plugins[i]->name != nullptr ? m_cp_plugins[i]->name : "",
440                state_to_string(cp_get_plugin_state(m_context, m_cp_plugins[i]->identifier)),
441                m_cp_plugins[i]->resourcetype != nullptr ? m_cp_plugins[i]->resourcetype : "");
442     }
443     printf("\n");
444 }
445
446 int CpluffAdapter::start(Plugin *const plugin, void *const arg)
447 {
448     //printf("start\n");
449     std::string id;
450     cp_status_t status;
451     cp_context_t *ctx;
452
453     id = plugin->getID();
454     for (unsigned int i = 0 ; i < m_plugins.size(); i++)
455     {
456         if (*plugin == m_plugins[i])
457         {
458             ctx = cpi_new_context((cp_plugin_t *)hnode_get(hash_lookup(m_context->env->plugins, id.c_str())),
459                                   m_context->env, &status);
460             //cp_define_symbol(ctx, "START_ARGUMENT", arg);
461             //printf("start ocplatform address : %x\n", arg);
462
463             if ((status = cp_start_plugin(m_context, (char *)id.c_str()) ) != CP_OK)
464             {
465                 printf("API function CpluffAdapter::start() faild with error code.\n");
466                 return FALSE;
467             }
468             else
469             {
470                 printf("start plug-in %s.\n", (char *)id.c_str());
471             }
472
473             break;
474         }
475     }
476     return TRUE;
477 }
478
479 int CpluffAdapter::stop(Plugin *const plugin)
480 {
481     std::string id;
482     cp_status_t status;
483
484     id = plugin->getID();
485     printf("stop plugin id = %s\n", id.c_str());
486     if ((status = cp_stop_plugin(m_context, (char *)id.c_str())) != CP_OK)
487     {
488         printf("API function CpluffAdapter::stop() faild with error code.\n");
489         return FALSE;
490     }
491     else
492     {
493         printf("Stop plug-in %s.\n", (char *)id.c_str());
494     }
495
496     return TRUE;
497 }
498
499 bool CpluffAdapter::isStarted(Plugin *plugin)
500 {
501     std::string id;
502     cp_plugin_state_t state;
503
504     id = plugin->getID();
505
506     state = cp_get_plugin_state(m_context, (char *)id.c_str());
507     if (state == CP_PLUGIN_STARTING || state == CP_PLUGIN_ACTIVE)
508     {
509         return TRUE;
510     }
511     return FALSE;
512 }
513 //Auto plugin detection is disabled
514 /*
515 void CpluffAdapter::observePluginPath(void *str)
516 {
517     //printf("start observePluginPath\n");
518     int length;
519     int i = 0;
520     int fd;
521     int wd;
522     char *str1 = (char *)str;
523     std::string original_path(str1);
524     //printf("Directory is %s\n",(char*)str1));
525     char buffer[BUF_LEN];
526
527     fd = inotify_init();
528
529     if ( fd < 0 )
530     {
531         printf("inotify_init\n");
532     }
533
534     wd = inotify_add_watch( fd, str1,
535                             IN_MODIFY | IN_CREATE | IN_DELETE | IN_DELETE_SELF
536                             | IN_MOVE_SELF | IN_MOVED_FROM | IN_MOVED_TO);
537
538     while (true)
539     {
540         //printf("read start\n");
541         i = 0;
542         length = read( fd, buffer, BUF_LEN );
543
544         if ( length < 0 )
545         {
546             printf("observePluginPath read\n");
547         }
548         std::string filepath = original_path;
549         //printf("filepath = %s\n",filepath.c_str());
550         while ( i < length )
551         {
552             if (i < (signed)(BUF_LEN  - ( sizeof( struct inotify_event) + 16)) && i > -1)
553             {
554                 struct inotify_event *event = ( struct inotify_event *) &buffer[ i ];
555
556                 if ((event->mask & IN_CREATE) || (event->mask & IN_MODIFY) || (event->mask & IN_MOVED_TO))
557                 {
558                     registerAllPlugin(str1);
559                 }
560                 else
561                 {
562                     //filepath += "/";
563                     //filepath += std::string(event->name);
564                     std::vector<Plugin> *resource_plugin = findPlugins("Path", filepath.c_str()); //add foldername
565
566                     //printf("plugin size is %d\n",resource_plugin->size());
567                     //printf("plugin file path is %s\n",resource_plugin->());
568                     if (resource_plugin->size() == 1)
569                     {
570                         unregisterPlugin(&(resource_plugin->at(0)));
571                     }
572                     else
573                     {
574                         registerAllPlugin(str1);
575                     }
576                     delete(resource_plugin);
577                     resource_plugin = nullptr;
578                 }
579                 //printf("observePluginPath path = %s \n",str1);
580                 //printf("observePluginPath directory name = %s \n",event->name);
581                 i += EVENT_SIZE + event->len;
582             }
583         }
584
585
586     }
587     ( void ) inotify_rm_watch( fd, wd );
588     ( void ) close( fd );
589     //printf("observePluginPath end\n");
590 }
591 */
592 const std::string CpluffAdapter::getState(const std::string plugID)
593 {
594     return state_to_string(cp_get_plugin_state(m_context, plugID.c_str()));
595 }