Imported Upstream version 0.9.1
[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         if (!m_plugins[i].getValueByAttribute(key).compare(value))
317         {
318             re_plugins->push_back(m_plugins[i]);
319         }
320     }
321
322     return re_plugins;
323 }
324
325 /*
326 Plugin *CpluffAdapter::getPlugin(const std::string plugID)
327 {
328     for (unsigned int i = 0; i < m_plugins.size(); i++)
329     {
330         if (!(m_plugins[i].getID().compare(plugID)))
331         {
332             return &(m_plugins[i]);
333         }
334     }
335
336     return nullptr;
337 }
338 */
339
340 bool CpluffAdapter::getFileList(File_list &list, const std::string strDir)
341 {
342     struct stat statinfo;
343     memset(&statinfo, 0, sizeof(statinfo));
344     std::string path = strDir;
345     if (0 != lstat(path.c_str(), &statinfo))
346     {
347         printf("OICPlugManager lstat is 0\n");
348         return false;
349     }
350     if (!S_ISDIR(statinfo.st_mode))
351     {
352         printf("%s is not directory", strDir.c_str());
353         return false;
354     }
355
356     DIR *dir;
357     struct dirent *entry;
358
359     if ((dir = opendir(strDir.c_str())) == nullptr)
360     {
361         printf("%s open error", strDir.c_str());
362         return false;
363     }
364
365     while ((entry = readdir(dir)) != nullptr)
366     {
367         memset(&statinfo, 0, sizeof(statinfo));
368         std::string strFilePath = strDir + "/" + entry->d_name;
369         while (strFilePath.find("//") != std::string::npos)
370             strFilePath.replace(strFilePath.find("//"), 2, "/");
371
372         if (0 != lstat(strFilePath.c_str(), &statinfo))
373         {
374             printf("OICPlugManager lstat is 0\n");
375             closedir(dir);
376             return false;
377         }
378
379         if (S_ISDIR(statinfo.st_mode))
380         {
381             if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0)
382                 continue;
383
384             list.insert(std::pair<std::string, bool>(strFilePath, true));
385             std::string strSubDir = strDir + "/" + entry->d_name;
386             getFileList(list, strSubDir);
387         }
388         else
389         {
390             int size = strFilePath.size();
391             std::string so = strFilePath.substr(size - 2, size - 1);
392             if (so  == "so")
393             {
394                 list.insert(std::pair<std::string, bool>(strFilePath, false));
395             }
396         }
397     }
398     closedir(dir);
399
400     return true;
401 }
402
403 const char *CpluffAdapter::state_to_string(int state)
404 {
405     switch (state)
406     {
407         case 0:
408             return "UNINTALLED";
409         case 1:
410             return "INSTALLED";
411         case 2:
412             return "RESOLVED";
413         case 3:
414             return "STARTING";
415         case 4:
416             return "STOPPING";
417         case 5:
418             return "ACTIVE";
419         default:
420             return "Unknown";
421     }
422 }
423
424 void CpluffAdapter::printPluginList()
425 {
426     const char format[] = "  %-30s %-15s %-15s %-20s\n";
427     printf("\n====== Plugins List ======\n");
428     printf(format,
429            "ID",
430            "NAME",
431            "STATE",
432            "TYPE");
433
434     for (int i = 0; m_cp_plugins[i] != nullptr; i++)
435     {
436         printf(format,
437                m_cp_plugins[i]->identifier,
438                m_cp_plugins[i]->name != nullptr ? m_cp_plugins[i]->name : "",
439                state_to_string(cp_get_plugin_state(m_context, m_cp_plugins[i]->identifier)),
440                m_cp_plugins[i]->resourcetype != nullptr ? m_cp_plugins[i]->resourcetype : "");
441     }
442     printf("\n");
443 }
444
445 int CpluffAdapter::start(Plugin *const plugin, void *const arg)
446 {
447     std::string id;
448     cp_status_t status;
449
450     id = plugin->getID();
451     for (unsigned int i = 0 ; i < m_plugins.size(); i++)
452     {
453         if (*plugin == m_plugins[i])
454         {
455             if ((status = cp_start_plugin(m_context, (char *)id.c_str()) ) != CP_OK)
456             {
457                 printf("API function CpluffAdapter::start() faild with error code.\n");
458                 return FALSE;
459             }
460             else
461             {
462                 printf("start plug-in %s.\n", (char *)id.c_str());
463             }
464
465             break;
466         }
467     }
468     return TRUE;
469 }
470
471 int CpluffAdapter::stop(Plugin *const plugin)
472 {
473     std::string id;
474     cp_status_t status;
475
476     id = plugin->getID();
477     printf("stop plugin id = %s\n", id.c_str());
478     if ((status = cp_stop_plugin(m_context, (char *)id.c_str())) != CP_OK)
479     {
480         printf("API function CpluffAdapter::stop() faild with error code.\n");
481         return FALSE;
482     }
483     else
484     {
485         printf("Stop plug-in %s.\n", (char *)id.c_str());
486     }
487
488     return TRUE;
489 }
490
491 bool CpluffAdapter::isStarted(Plugin *plugin)
492 {
493     std::string id;
494     cp_plugin_state_t state;
495
496     id = plugin->getID();
497
498     state = cp_get_plugin_state(m_context, (char *)id.c_str());
499     if (state == CP_PLUGIN_STARTING || state == CP_PLUGIN_ACTIVE)
500     {
501         return TRUE;
502     }
503     return FALSE;
504 }
505
506 // Auto plugin detection is disabled
507 /*
508 void CpluffAdapter::observePluginPath(void *str)
509 {
510     int length;
511     int i = 0;
512     int fd;
513     int wd;
514     char *str1 = (char *)str;
515     std::string original_path(str1);
516     char buffer[BUF_LEN];
517
518     fd = inotify_init();
519
520     if ( fd < 0 )
521     {
522         printf("inotify_init\n");
523     }
524
525     wd = inotify_add_watch( fd, str1,
526                             IN_MODIFY | IN_CREATE | IN_DELETE | IN_DELETE_SELF
527                             | IN_MOVE_SELF | IN_MOVED_FROM | IN_MOVED_TO);
528
529     while (true)
530     {
531         //printf("read start\n");
532         i = 0;
533         length = read( fd, buffer, BUF_LEN );
534
535         if ( length < 0 )
536         {
537             printf("observePluginPath read\n");
538         }
539         std::string filepath = original_path;
540         while ( i < length )
541         {
542             if (i < (signed)(BUF_LEN  - ( sizeof( struct inotify_event) + 16)) && i > -1)
543             {
544                 struct inotify_event *event = ( struct inotify_event *) &buffer[ i ];
545
546                 if ((event->mask & IN_CREATE) || (event->mask & IN_MODIFY) || (event->mask & IN_MOVED_TO))
547                 {
548                     registerAllPlugin(str1);
549                 }
550                 else
551                 {
552                     std::vector<Plugin> *resource_plugin = findPlugins("Path", filepath.c_str()); //add foldername
553
554                     if (resource_plugin->size() == 1)
555                     {
556                         unregisterPlugin(&(resource_plugin->at(0)));
557                     }
558                     else
559                     {
560                         registerAllPlugin(str1);
561                     }
562                     delete(resource_plugin);
563                     resource_plugin = nullptr;
564                 }
565                 i += EVENT_SIZE + event->len;
566             }
567         }
568
569
570     }
571     ( void ) inotify_rm_watch( fd, wd );
572     ( void ) close( fd );
573 }
574 */
575
576 const std::string CpluffAdapter::getState(const std::string plugID)
577 {
578     return state_to_string(cp_get_plugin_state(m_context, plugID.c_str()));
579 }