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