Fix for the Jira issue IOT-538
[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(void *args)
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(args);
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     }
215
216     return TRUE;
217 }
218
219 int CpluffAdapter::registerPlugin(const std::string path)
220 {
221     int flag = FALSE;
222
223     if (path == "")
224     {
225         printf("CpluffAdapter path == null\n");
226         return flag;
227     }
228
229     //non recursive
230     if (installPlugin(path))
231     {
232         flag = loadPluginInfoToManager(path);
233     }
234     return flag;
235 }
236
237 int CpluffAdapter::registerAllPlugin(const std::string path)
238 {
239     int flag = FALSE;
240     if (path == "")
241     {
242         printf("CpluffAdapter path == null\n");
243         return flag;
244     }
245
246     //recursive
247     if (findPluginRecursive(path))
248     {
249         flag = loadPluginInfoToManager(path);
250     }
251     return flag;
252 }
253
254 int CpluffAdapter::unregisterPlugin(Plugin *const plugin)
255 {
256     cp_status_t status;
257     char *argv = nullptr;
258     std::string id = "";
259
260     for (unsigned int i = 0; i < m_plugins.size(); i++)
261     {
262
263         if (*plugin == m_plugins[i])
264         {
265             id = m_plugins[i].getID().c_str();
266             argv = const_cast<char *>(id.c_str());
267             if ((status = cp_uninstall_plugin(m_context, argv)) != 0)
268             {
269                 printf("unregister failed\n");
270                 return FALSE;
271             }
272             m_plugins.erase(m_plugins.begin() + i);
273         }
274     }
275     return TRUE;
276 }
277
278 int CpluffAdapter::unregisterAllPlugin(void)
279 {
280     cp_status_t status;
281     char *argv = nullptr;
282     std::string id = "";
283
284     while (true)
285     {
286         id = m_plugins[0].getID().c_str();
287         argv = const_cast<char *>(id.c_str());
288         if ((status = cp_uninstall_plugin(m_context, argv)) != 0)
289         {
290             printf("unregister failed\n");
291             return FALSE;
292         }
293         m_plugins.erase(m_plugins.begin());
294         if (m_plugins.size() == 0)
295         {
296             break;
297         }
298     }
299
300     return TRUE;
301 }
302
303 std::vector<Plugin> &CpluffAdapter::getAllPlugins(void)
304 {
305     return m_plugins;
306 }
307
308 std::vector<Plugin> *CpluffAdapter::findPlugins(const std::string key, const std::string value)
309 {
310     std::vector<Plugin> *re_plugins;
311
312     re_plugins = new std::vector<Plugin>;
313
314     for (unsigned int i = 0; i < m_plugins.size(); i++)
315     {
316         std::string attributeValue = m_plugins[i].getValueByAttribute(key);
317         if (!attributeValue.empty() && !attributeValue.compare(value))
318         {
319             re_plugins->push_back(m_plugins[i]);
320         }
321     }
322
323     return re_plugins;
324 }
325
326 /*
327 Plugin *CpluffAdapter::getPlugin(const std::string plugID)
328 {
329     for (unsigned int i = 0; i < m_plugins.size(); i++)
330     {
331         if (!(m_plugins[i].getID().compare(plugID)))
332         {
333             return &(m_plugins[i]);
334         }
335     }
336
337     return nullptr;
338 }
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     std::string id;
449     cp_status_t status;
450
451     id = plugin->getID();
452     for (unsigned int i = 0 ; i < m_plugins.size(); i++)
453     {
454         if (*plugin == m_plugins[i])
455         {
456             if ((status = cp_start_plugin(m_context, (char *)id.c_str()) ) != CP_OK)
457             {
458                 printf("API function CpluffAdapter::start() faild with error code.\n");
459                 return FALSE;
460             }
461             else
462             {
463                 printf("start plug-in %s.\n", (char *)id.c_str());
464             }
465
466             break;
467         }
468     }
469     return TRUE;
470 }
471
472 int CpluffAdapter::stop(Plugin *const plugin)
473 {
474     std::string id;
475     cp_status_t status;
476
477     id = plugin->getID();
478     printf("stop plugin id = %s\n", id.c_str());
479     if ((status = cp_stop_plugin(m_context, (char *)id.c_str())) != CP_OK)
480     {
481         printf("API function CpluffAdapter::stop() faild with error code.\n");
482         return FALSE;
483     }
484     else
485     {
486         printf("Stop plug-in %s.\n", (char *)id.c_str());
487     }
488
489     return TRUE;
490 }
491
492 bool CpluffAdapter::isStarted(Plugin *plugin)
493 {
494     std::string id;
495     cp_plugin_state_t state;
496
497     id = plugin->getID();
498
499     state = cp_get_plugin_state(m_context, (char *)id.c_str());
500     if (state == CP_PLUGIN_STARTING || state == CP_PLUGIN_ACTIVE)
501     {
502         return TRUE;
503     }
504     return FALSE;
505 }
506
507 // Auto plugin detection is disabled
508 /*
509 void CpluffAdapter::observePluginPath(void *str)
510 {
511     int length;
512     int i = 0;
513     int fd;
514     int wd;
515     char *str1 = (char *)str;
516     std::string original_path(str1);
517     char buffer[BUF_LEN];
518
519     fd = inotify_init();
520
521     if ( fd < 0 )
522     {
523         printf("inotify_init\n");
524     }
525
526     wd = inotify_add_watch( fd, str1,
527                             IN_MODIFY | IN_CREATE | IN_DELETE | IN_DELETE_SELF
528                             | IN_MOVE_SELF | IN_MOVED_FROM | IN_MOVED_TO);
529
530     while (true)
531     {
532         //printf("read start\n");
533         i = 0;
534         length = read( fd, buffer, BUF_LEN );
535
536         if ( length < 0 )
537         {
538             printf("observePluginPath read\n");
539         }
540         std::string filepath = original_path;
541         while ( i < length )
542         {
543             if (i < (signed)(BUF_LEN  - ( sizeof( struct inotify_event) + 16)) && i > -1)
544             {
545                 struct inotify_event *event = ( struct inotify_event *) &buffer[ i ];
546
547                 if ((event->mask & IN_CREATE) || (event->mask & IN_MODIFY) || (event->mask & IN_MOVED_TO))
548                 {
549                     registerAllPlugin(str1);
550                 }
551                 else
552                 {
553                     std::vector<Plugin> *resource_plugin = findPlugins("Path", filepath.c_str()); //add foldername
554
555                     if (resource_plugin->size() == 1)
556                     {
557                         unregisterPlugin(&(resource_plugin->at(0)));
558                     }
559                     else
560                     {
561                         registerAllPlugin(str1);
562                     }
563                     delete(resource_plugin);
564                     resource_plugin = nullptr;
565                 }
566                 i += EVENT_SIZE + event->len;
567             }
568         }
569
570
571     }
572     ( void ) inotify_rm_watch( fd, wd );
573     ( void ) close( fd );
574 }
575 */
576
577 const std::string CpluffAdapter::getState(const std::string plugID)
578 {
579     return state_to_string(cp_get_plugin_state(m_context, plugID.c_str()));
580 }